diff --git a/cmd/tailscale/depaware.txt b/cmd/tailscale/depaware.txt index 5d1a82974..cfd67c673 100644 --- a/cmd/tailscale/depaware.txt +++ b/cmd/tailscale/depaware.txt @@ -20,7 +20,6 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep go4.org/unsafe/assume-no-moving-gc from go4.org/intern W 💣 golang.zx2c4.com/wireguard/windows/tunnel/winipcfg from tailscale.com/net/interfaces+ inet.af/netaddr from tailscale.com/cmd/tailscale/cli+ - rsc.io/goversion/version from tailscale.com/version tailscale.com/atomicfile from tailscale.com/ipn tailscale.com/client/tailscale from tailscale.com/cmd/tailscale/cli+ tailscale.com/client/tailscale/apitype from tailscale.com/client/tailscale+ @@ -101,9 +100,8 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep golang.org/x/time/rate from tailscale.com/cmd/tailscale/cli+ bufio from compress/flate+ bytes from bufio+ - compress/flate from compress/gzip+ + compress/flate from compress/gzip compress/gzip from net/http - compress/zlib from debug/elf+ container/list from crypto/tls+ context from crypto/tls+ crypto from crypto/ecdsa+ @@ -126,10 +124,6 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep crypto/tls from github.com/tcnksm/go-httpstat+ crypto/x509 from crypto/tls+ crypto/x509/pkix from crypto/x509+ - debug/dwarf from debug/elf+ - debug/elf from rsc.io/goversion/version - debug/macho from rsc.io/goversion/version - debug/pe from rsc.io/goversion/version embed from tailscale.com/cmd/tailscale/cli encoding from encoding/json+ encoding/asn1 from crypto/x509+ @@ -143,8 +137,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep expvar from tailscale.com/derp+ flag from github.com/peterbourgon/ff/v2+ fmt from compress/flate+ - hash from compress/zlib+ - hash/adler32 from compress/zlib + hash from crypto+ hash/crc32 from compress/gzip+ hash/maphash from go4.org/mem html from tailscale.com/ipn/ipnstate+ @@ -171,10 +164,10 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep os/exec from github.com/toqueteos/webbrowser+ os/signal from tailscale.com/cmd/tailscale/cli os/user from tailscale.com/util/groupmember - path from debug/dwarf+ + path from html/template+ path/filepath from crypto/x509+ reflect from crypto/x509+ - regexp from rsc.io/goversion/version+ + regexp from github.com/tailscale/goupnp/httpu+ regexp/syntax from regexp runtime/debug from golang.org/x/sync/singleflight sort from compress/flate+ diff --git a/cmd/tailscaled/depaware.txt b/cmd/tailscaled/depaware.txt index 41dde5cca..4e5ab8c59 100644 --- a/cmd/tailscaled/depaware.txt +++ b/cmd/tailscaled/depaware.txt @@ -87,7 +87,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de inet.af/netstack/waiter from inet.af/netstack/tcpip+ inet.af/peercred from tailscale.com/ipn/ipnserver W 💣 inet.af/wf from tailscale.com/wf - rsc.io/goversion/version from tailscale.com/version tailscale.com/atomicfile from tailscale.com/ipn+ tailscale.com/client/tailscale from tailscale.com/derp tailscale.com/client/tailscale/apitype from tailscale.com/ipn/ipnlocal+ @@ -216,9 +215,8 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de golang.org/x/time/rate from inet.af/netstack/tcpip/stack+ bufio from compress/flate+ bytes from bufio+ - compress/flate from compress/gzip+ + compress/flate from compress/gzip compress/gzip from internal/profile+ - compress/zlib from debug/elf+ container/heap from inet.af/netstack/tcpip/transport/tcp container/list from crypto/tls+ context from crypto/tls+ @@ -242,10 +240,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de crypto/tls from github.com/tcnksm/go-httpstat+ crypto/x509 from crypto/tls+ crypto/x509/pkix from crypto/x509+ - debug/dwarf from debug/elf+ - debug/elf from rsc.io/goversion/version - debug/macho from rsc.io/goversion/version - debug/pe from rsc.io/goversion/version embed from tailscale.com/net/dns+ encoding from encoding/json+ encoding/asn1 from crypto/x509+ @@ -259,8 +253,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de expvar from tailscale.com/derp+ flag from tailscale.com/cmd/tailscaled+ fmt from compress/flate+ - hash from compress/zlib+ - hash/adler32 from compress/zlib + hash from crypto+ hash/crc32 from compress/gzip+ hash/fnv from tailscale.com/wgengine/magicsock+ hash/maphash from go4.org/mem @@ -288,7 +281,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de os/exec from github.com/coreos/go-iptables/iptables+ os/signal from tailscale.com/cmd/tailscaled+ os/user from github.com/godbus/dbus/v5+ - path from debug/dwarf+ + path from github.com/godbus/dbus/v5+ path/filepath from crypto/x509+ reflect from crypto/x509+ regexp from github.com/coreos/go-iptables/iptables+ diff --git a/go.mod b/go.mod index cdcd59e4e..b5fd115e8 100644 --- a/go.mod +++ b/go.mod @@ -51,5 +51,4 @@ require ( inet.af/netstack v0.0.0-20210622165351-29b14ebc044e inet.af/peercred v0.0.0-20210318190834-4259e17bb763 inet.af/wf v0.0.0-20210516214145-a5343001b756 - rsc.io/goversion v1.2.0 ) diff --git a/version/cmdname.go b/version/cmdname.go index 9bccece03..791551d2e 100644 --- a/version/cmdname.go +++ b/version/cmdname.go @@ -8,12 +8,14 @@ package version import ( + "bytes" + "encoding/hex" + "errors" + "io" "os" "path" "path/filepath" "strings" - - "rsc.io/goversion/version" ) // CmdName returns either the base name of the current binary @@ -30,13 +32,13 @@ func CmdName() string { fallbackName := filepath.Base(strings.TrimSuffix(strings.ToLower(e), ".exe")) var ret string - v, err := version.ReadExe(e) + info, err := findModuleInfo(e) 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(v.ModuleInfo, "\n") { + for _, line := range strings.Split(info, "\n") { if strings.HasPrefix(line, "path\t") { goPkg := strings.TrimPrefix(line, "path\t") // like "tailscale.com/cmd/tailscale" ret = path.Base(goPkg) // goPkg is always forward slashes; use path, not filepath @@ -48,3 +50,84 @@ func CmdName() string { } 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") +) diff --git a/version/modinfo_test.go b/version/modinfo_test.go new file mode 100644 index 000000000..c7c1a14a3 --- /dev/null +++ b/version/modinfo_test.go @@ -0,0 +1,29 @@ +// 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 version + +import ( + "os/exec" + "path/filepath" + "strings" + "testing" +) + +func TestFindModuleInfo(t *testing.T) { + dir := t.TempDir() + name := filepath.Join(dir, "tailscaled-version-test") + out, err := exec.Command("go", "build", "-o", name, "tailscale.com/cmd/tailscaled").CombinedOutput() + if err != nil { + t.Fatalf("failed to build tailscaled: %v\n%s", err, out) + } + modinfo, err := findModuleInfo(name) + if err != nil { + t.Fatal(err) + } + prefix := "path\ttailscale.com/cmd/tailscaled\nmod\ttailscale.com" + if !strings.HasPrefix(modinfo, prefix) { + t.Errorf("unexpected modinfo contents %q", modinfo) + } +}