diff options
Diffstat (limited to 'version/cmdname.go')
| -rw-r--r-- | version/cmdname.go | 278 |
1 files changed, 139 insertions, 139 deletions
diff --git a/version/cmdname.go b/version/cmdname.go index 51e065438..9f85ef96d 100644 --- a/version/cmdname.go +++ b/version/cmdname.go @@ -1,139 +1,139 @@ -// Copyright (c) Tailscale Inc & AUTHORS -// SPDX-License-Identifier: BSD-3-Clause - -//go:build !ios - -package version - -import ( - "bytes" - "encoding/hex" - "errors" - "io" - "os" - "path" - "path/filepath" - "strings" -) - -// CmdName returns either the base name of the current binary -// using os.Executable. If os.Executable fails (it shouldn't), then -// "cmd" is returned. -func CmdName() string { - e, err := os.Executable() - if err != nil { - return "cmd" - } - return cmdName(e) -} - -func cmdName(exe string) string { - // fallbackName, the lowercase basename of the executable, is what we return if - // we can't find the Go module metadata embedded in the file. - fallbackName := filepath.Base(strings.TrimSuffix(strings.ToLower(exe), ".exe")) - - var ret string - info, err := findModuleInfo(exe) - if err != nil { - return fallbackName - } - // v is like: - // "path\ttailscale.com/cmd/tailscale\nmod\ttailscale.com\t(devel)\t\ndep\tgithub.com/apenwarr/fixconsole\tv0.0.0-20191012055117-5a9f6489cc29\th1:muXWUcay7DDy1/hEQWrYlBy+g0EuwT70sBHg65SeUc4=\ndep\tgithub.... - for _, line := range strings.Split(info, "\n") { - if goPkg, ok := strings.CutPrefix(line, "path\t"); ok { // like "tailscale.com/cmd/tailscale" - ret = path.Base(goPkg) // goPkg is always forward slashes; use path, not filepath - break - } - } - if strings.HasPrefix(ret, "wg") && fallbackName == "tailscale-ipn" { - // The tailscale-ipn.exe binary for internal build system packaging reasons - // has a path of "tailscale.io/win/wg64", "tailscale.io/win/wg32", etc. - // Ignore that name and use "tailscale-ipn" instead. - return fallbackName - } - if ret == "" { - return fallbackName - } - return ret -} - -// findModuleInfo returns the Go module info from the executable file. -func findModuleInfo(file string) (s string, err error) { - f, err := os.Open(file) - if err != nil { - return "", err - } - defer f.Close() - // Scan through f until we find infoStart. - buf := make([]byte, 65536) - start, err := findOffset(f, buf, infoStart) - if err != nil { - return "", err - } - start += int64(len(infoStart)) - // Seek to the end of infoStart and scan for infoEnd. - _, err = f.Seek(start, io.SeekStart) - if err != nil { - return "", err - } - end, err := findOffset(f, buf, infoEnd) - if err != nil { - return "", err - } - length := end - start - // As of Aug 2021, tailscaled's mod info was about 2k. - if length > int64(len(buf)) { - return "", errors.New("mod info too large") - } - // We have located modinfo. Read it into buf. - buf = buf[:length] - _, err = f.Seek(start, io.SeekStart) - if err != nil { - return "", err - } - _, err = io.ReadFull(f, buf) - if err != nil { - return "", err - } - return string(buf), nil -} - -// findOffset finds the absolute offset of needle in f, -// starting at f's current read position, -// using temporary buffer buf. -func findOffset(f *os.File, buf, needle []byte) (int64, error) { - for { - // Fill buf and look within it. - n, err := f.Read(buf) - if err != nil { - return -1, err - } - i := bytes.Index(buf[:n], needle) - if i < 0 { - // Not found. Rewind a little bit in case we happened to end halfway through needle. - rewind, err := f.Seek(int64(-len(needle)), io.SeekCurrent) - if err != nil { - return -1, err - } - // If we're at EOF and rewound exactly len(needle) bytes, return io.EOF. - _, err = f.ReadAt(buf[:1], rewind+int64(len(needle))) - if err == io.EOF { - return -1, err - } - continue - } - // Found! Figure out exactly where. - cur, err := f.Seek(0, io.SeekCurrent) - if err != nil { - return -1, err - } - return cur - int64(n) + int64(i), nil - } -} - -// These constants are taken from rsc.io/goversion. - -var ( - infoStart, _ = hex.DecodeString("3077af0c9274080241e1c107e6d618e6") - infoEnd, _ = hex.DecodeString("f932433186182072008242104116d8f2") -) +// Copyright (c) Tailscale Inc & AUTHORS
+// SPDX-License-Identifier: BSD-3-Clause
+
+//go:build !ios
+
+package version
+
+import (
+ "bytes"
+ "encoding/hex"
+ "errors"
+ "io"
+ "os"
+ "path"
+ "path/filepath"
+ "strings"
+)
+
+// CmdName returns either the base name of the current binary
+// using os.Executable. If os.Executable fails (it shouldn't), then
+// "cmd" is returned.
+func CmdName() string {
+ e, err := os.Executable()
+ if err != nil {
+ return "cmd"
+ }
+ return cmdName(e)
+}
+
+func cmdName(exe string) string {
+ // fallbackName, the lowercase basename of the executable, is what we return if
+ // we can't find the Go module metadata embedded in the file.
+ fallbackName := filepath.Base(strings.TrimSuffix(strings.ToLower(exe), ".exe"))
+
+ var ret string
+ info, err := findModuleInfo(exe)
+ if err != nil {
+ return fallbackName
+ }
+ // v is like:
+ // "path\ttailscale.com/cmd/tailscale\nmod\ttailscale.com\t(devel)\t\ndep\tgithub.com/apenwarr/fixconsole\tv0.0.0-20191012055117-5a9f6489cc29\th1:muXWUcay7DDy1/hEQWrYlBy+g0EuwT70sBHg65SeUc4=\ndep\tgithub....
+ for _, line := range strings.Split(info, "\n") {
+ if goPkg, ok := strings.CutPrefix(line, "path\t"); ok { // like "tailscale.com/cmd/tailscale"
+ ret = path.Base(goPkg) // goPkg is always forward slashes; use path, not filepath
+ break
+ }
+ }
+ if strings.HasPrefix(ret, "wg") && fallbackName == "tailscale-ipn" {
+ // The tailscale-ipn.exe binary for internal build system packaging reasons
+ // has a path of "tailscale.io/win/wg64", "tailscale.io/win/wg32", etc.
+ // Ignore that name and use "tailscale-ipn" instead.
+ return fallbackName
+ }
+ if ret == "" {
+ return fallbackName
+ }
+ return ret
+}
+
+// findModuleInfo returns the Go module info from the executable file.
+func findModuleInfo(file string) (s string, err error) {
+ f, err := os.Open(file)
+ if err != nil {
+ return "", err
+ }
+ defer f.Close()
+ // Scan through f until we find infoStart.
+ buf := make([]byte, 65536)
+ start, err := findOffset(f, buf, infoStart)
+ if err != nil {
+ return "", err
+ }
+ start += int64(len(infoStart))
+ // Seek to the end of infoStart and scan for infoEnd.
+ _, err = f.Seek(start, io.SeekStart)
+ if err != nil {
+ return "", err
+ }
+ end, err := findOffset(f, buf, infoEnd)
+ if err != nil {
+ return "", err
+ }
+ length := end - start
+ // As of Aug 2021, tailscaled's mod info was about 2k.
+ if length > int64(len(buf)) {
+ return "", errors.New("mod info too large")
+ }
+ // We have located modinfo. Read it into buf.
+ buf = buf[:length]
+ _, err = f.Seek(start, io.SeekStart)
+ if err != nil {
+ return "", err
+ }
+ _, err = io.ReadFull(f, buf)
+ if err != nil {
+ return "", err
+ }
+ return string(buf), nil
+}
+
+// findOffset finds the absolute offset of needle in f,
+// starting at f's current read position,
+// using temporary buffer buf.
+func findOffset(f *os.File, buf, needle []byte) (int64, error) {
+ for {
+ // Fill buf and look within it.
+ n, err := f.Read(buf)
+ if err != nil {
+ return -1, err
+ }
+ i := bytes.Index(buf[:n], needle)
+ if i < 0 {
+ // Not found. Rewind a little bit in case we happened to end halfway through needle.
+ rewind, err := f.Seek(int64(-len(needle)), io.SeekCurrent)
+ if err != nil {
+ return -1, err
+ }
+ // If we're at EOF and rewound exactly len(needle) bytes, return io.EOF.
+ _, err = f.ReadAt(buf[:1], rewind+int64(len(needle)))
+ if err == io.EOF {
+ return -1, err
+ }
+ continue
+ }
+ // Found! Figure out exactly where.
+ cur, err := f.Seek(0, io.SeekCurrent)
+ if err != nil {
+ return -1, err
+ }
+ return cur - int64(n) + int64(i), nil
+ }
+}
+
+// These constants are taken from rsc.io/goversion.
+
+var (
+ infoStart, _ = hex.DecodeString("3077af0c9274080241e1c107e6d618e6")
+ infoEnd, _ = hex.DecodeString("f932433186182072008242104116d8f2")
+)
|
