| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- // Copyright (c) Tailscale Inc & AUTHORS
- // SPDX-License-Identifier: BSD-3-Clause
- //go:build !ios
- package version
- import (
- "bytes"
- "encoding/hex"
- "errors"
- "io"
- "os"
- "path"
- "runtime"
- "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 := prepExeNameForCmp(exe, runtime.GOARCH)
- 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 runtime.GOOS == "windows" && strings.HasPrefix(ret, "gui") && checkPreppedExeNameForGUI(fallbackName) {
- // The GUI binary for internal build system packaging reasons
- // has a path of "tailscale.io/win/gui".
- // Ignore that name and use fallbackName 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")
- )
|