mirror of
https://github.com/golang/go
synced 2024-11-05 11:46:12 -07:00
df83f4e7c1
Seems we've drifted a bit from go1.12 support, mostly due to error wrapping. Fix this, as well as some assorted other failures. I haven't tested 1.12 interactively. For golang/go#39146 Change-Id: Id347ead2a13e89b76d2ae0047750e6b6b49911eb Reviewed-on: https://go-review.googlesource.com/c/tools/+/250941 Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
99 lines
2.7 KiB
Go
99 lines
2.7 KiB
Go
// Copyright 2020 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
|
|
|
package lsprpc
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"errors"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"os/user"
|
|
"path/filepath"
|
|
"strconv"
|
|
"syscall"
|
|
|
|
"golang.org/x/xerrors"
|
|
)
|
|
|
|
func init() {
|
|
startRemote = startRemotePosix
|
|
autoNetworkAddress = autoNetworkAddressPosix
|
|
verifyRemoteOwnership = verifyRemoteOwnershipPosix
|
|
}
|
|
|
|
func startRemotePosix(goplsPath string, args ...string) error {
|
|
cmd := exec.Command(goplsPath, args...)
|
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
Setsid: true,
|
|
}
|
|
if err := cmd.Start(); err != nil {
|
|
return xerrors.Errorf("starting remote gopls: %w", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// autoNetworkAddress resolves an id on the 'auto' pseduo-network to a
|
|
// real network and address. On unix, this uses unix domain sockets.
|
|
func autoNetworkAddressPosix(goplsPath, id string) (network string, address string) {
|
|
// Especially when doing local development or testing, it's important that
|
|
// the remote gopls instance we connect to is running the same binary as our
|
|
// forwarder. So we encode a short hash of the binary path into the daemon
|
|
// socket name. If possible, we also include the buildid in this hash, to
|
|
// account for long-running processes where the binary has been subsequently
|
|
// rebuilt.
|
|
h := sha256.New()
|
|
cmd := exec.Command("go", "tool", "buildid", goplsPath)
|
|
cmd.Stdout = h
|
|
var pathHash []byte
|
|
if err := cmd.Run(); err == nil {
|
|
pathHash = h.Sum(nil)
|
|
} else {
|
|
log.Printf("error getting current buildid: %v", err)
|
|
sum := sha256.Sum256([]byte(goplsPath))
|
|
pathHash = sum[:]
|
|
}
|
|
shortHash := fmt.Sprintf("%x", pathHash)[:6]
|
|
user := os.Getenv("USER")
|
|
if user == "" {
|
|
user = "shared"
|
|
}
|
|
basename := filepath.Base(goplsPath)
|
|
idComponent := ""
|
|
if id != "" {
|
|
idComponent = "-" + id
|
|
}
|
|
return "unix", filepath.Join(os.TempDir(), fmt.Sprintf("%s-%s-daemon.%s%s", basename, shortHash, user, idComponent))
|
|
}
|
|
|
|
func verifyRemoteOwnershipPosix(network, address string) (bool, error) {
|
|
if network != "unix" {
|
|
return true, nil
|
|
}
|
|
fi, err := os.Stat(address)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return true, nil
|
|
}
|
|
return false, xerrors.Errorf("checking socket owner: %w", err)
|
|
}
|
|
stat, ok := fi.Sys().(*syscall.Stat_t)
|
|
if !ok {
|
|
return false, errors.New("fi.Sys() is not a Stat_t")
|
|
}
|
|
user, err := user.Current()
|
|
if err != nil {
|
|
return false, xerrors.Errorf("checking current user: %w", err)
|
|
}
|
|
uid, err := strconv.ParseUint(user.Uid, 10, 32)
|
|
if err != nil {
|
|
return false, xerrors.Errorf("parsing current UID: %w", err)
|
|
}
|
|
return stat.Uid == uint32(uid), nil
|
|
}
|