From 4fee32100458a7e75c65e297e5a6074ca0650ca3 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Tue, 22 Feb 2022 10:01:36 -0800 Subject: [PATCH] hostinfo: move packageType out to platform-specific files Change-Id: I3236b3d4e2376dd7e2482c2562817b1b6f44872e Signed-off-by: Brad Fitzpatrick --- hostinfo/hostinfo.go | 67 ++++++++---------------------------- hostinfo/hostinfo_darwin.go | 23 +++++++++++++ hostinfo/hostinfo_linux.go | 11 ++++++ hostinfo/hostinfo_windows.go | 38 ++++++++++++++++++++ 4 files changed, 86 insertions(+), 53 deletions(-) create mode 100644 hostinfo/hostinfo_darwin.go diff --git a/hostinfo/hostinfo.go b/hostinfo/hostinfo.go index 281466b31..59ced3d9f 100644 --- a/hostinfo/hostinfo.go +++ b/hostinfo/hostinfo.go @@ -10,7 +10,6 @@ import ( "bufio" "io" "os" - "path/filepath" "runtime" "strings" "sync/atomic" @@ -32,13 +31,17 @@ func New() *tailcfg.Hostinfo { Hostname: hostname, OS: version.OS(), OSVersion: GetOSVersion(), - Package: packageType(), + Package: packageTypeCached(), GoArch: runtime.GOARCH, DeviceModel: deviceModel(), } } -var osVersion func() string // non-nil on some platforms +// non-nil on some platforms +var ( + osVersion func() string + packageType func() string +) // GetOSVersion returns the OSVersion of current host if available. func GetOSVersion() string { @@ -51,60 +54,18 @@ func GetOSVersion() string { return "" } -func packageType() (ret string) { +func packageTypeCached() string { if v, _ := packagingType.Load().(string); v != "" { return v } - switch runtime.GOOS { - case "windows": - defer func() { - if ret != "" { - packagingType.Store(ret) - } - }() - if _, err := os.Stat(`C:\ProgramData\chocolatey\lib\tailscale`); err == nil { - return "choco" - } - exe, err := os.Executable() - if err != nil { - return "" - } - dir := filepath.Dir(exe) - if !strings.Contains(dir, "Program Files") { - // Atypical. Not worth trying to detect. Likely open - // source tailscaled or a developer running by hand. - return "" - } - nsisUninstaller := filepath.Join(dir, "Uninstall-Tailscale.exe") - _, err = os.Stat(nsisUninstaller) - if err == nil { - return "nsis" - } - if os.IsNotExist(err) { - _, cliErr := os.Stat(filepath.Join(dir, "tailscale.exe")) - _, daemonErr := os.Stat(filepath.Join(dir, "tailscaled.exe")) - if cliErr == nil && daemonErr == nil { - // Almost certainly MSI. - // We have tailscaled.exe and tailscale.exe - // next to each other in Program Files, but no - // uninstaller. - // TODO(bradfitz,dblohm7): tighter heuristic? - return "msi" - } - } - case "darwin": - // Using tailscaled or IPNExtension? - exe, _ := os.Executable() - return filepath.Base(exe) - case "linux": - // Report whether this is in a snap. - // See https://snapcraft.io/docs/environment-variables - // We just look at two somewhat arbitrarily. - if os.Getenv("SNAP_NAME") != "" && os.Getenv("SNAP") != "" { - return "snap" - } + if packageType == nil { + return "" } - return "" + v := packageType() + if v != "" { + SetPackage(v) + } + return v } // EnvType represents a known environment type. diff --git a/hostinfo/hostinfo_darwin.go b/hostinfo/hostinfo_darwin.go new file mode 100644 index 000000000..367fd1d5e --- /dev/null +++ b/hostinfo/hostinfo_darwin.go @@ -0,0 +1,23 @@ +// Copyright (c) 2022 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. + +//go:build darwin +// +build darwin + +package hostinfo + +import ( + "os" + "path/filepath" +) + +func init() { + packageType = packageTypeDarwin +} + +func packageTypeDarwin() string { + // Using tailscaled or IPNExtension? + exe, _ := os.Executable() + return filepath.Base(exe) +} diff --git a/hostinfo/hostinfo_linux.go b/hostinfo/hostinfo_linux.go index f9bd5b283..e2a878be6 100644 --- a/hostinfo/hostinfo_linux.go +++ b/hostinfo/hostinfo_linux.go @@ -21,6 +21,7 @@ import ( func init() { osVersion = osVersionLinux + packageType = packageTypeLinux if v := linuxDeviceModel(); v != "" { SetDeviceModel(v) @@ -115,3 +116,13 @@ func osVersionLinux() string { } return fmt.Sprintf("Other%s", attr) } + +func packageTypeLinux() string { + // Report whether this is in a snap. + // See https://snapcraft.io/docs/environment-variables + // We just look at two somewhat arbitrarily. + if os.Getenv("SNAP_NAME") != "" && os.Getenv("SNAP") != "" { + return "snap" + } + return "" +} diff --git a/hostinfo/hostinfo_windows.go b/hostinfo/hostinfo_windows.go index 2df088f4b..aa78cde2e 100644 --- a/hostinfo/hostinfo_windows.go +++ b/hostinfo/hostinfo_windows.go @@ -6,6 +6,9 @@ package hostinfo import ( "fmt" + "os" + "path/filepath" + "strings" "sync/atomic" "golang.org/x/sys/windows" @@ -14,6 +17,7 @@ import ( func init() { osVersion = osVersionWindows + packageType = packageTypeWindows } var winVerCache atomic.Value // of string @@ -56,3 +60,37 @@ func getUBR() (uint32, error) { return uint32(val), nil } + +func packageTypeWindows() string { + if _, err := os.Stat(`C:\ProgramData\chocolatey\lib\tailscale`); err == nil { + return "choco" + } + exe, err := os.Executable() + if err != nil { + return "" + } + dir := filepath.Dir(exe) + if !strings.Contains(dir, "Program Files") { + // Atypical. Not worth trying to detect. Likely open + // source tailscaled or a developer running by hand. + return "" + } + nsisUninstaller := filepath.Join(dir, "Uninstall-Tailscale.exe") + _, err = os.Stat(nsisUninstaller) + if err == nil { + return "nsis" + } + if os.IsNotExist(err) { + _, cliErr := os.Stat(filepath.Join(dir, "tailscale.exe")) + _, daemonErr := os.Stat(filepath.Join(dir, "tailscaled.exe")) + if cliErr == nil && daemonErr == nil { + // Almost certainly MSI. + // We have tailscaled.exe and tailscale.exe + // next to each other in Program Files, but no + // uninstaller. + // TODO(bradfitz,dblohm7): tighter heuristic? + return "msi" + } + } + return "" +}