.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.1-0.20210319172145-bda8f5cee399 / internal / lsp / lsprpc / autostart_posix.go
1 // Copyright 2020 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 //go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
6 // +build darwin dragonfly freebsd linux netbsd openbsd solaris
7
8 package lsprpc
9
10 import (
11         "crypto/sha256"
12         "errors"
13         "fmt"
14         exec "golang.org/x/sys/execabs"
15         "log"
16         "os"
17         "os/user"
18         "path/filepath"
19         "strconv"
20         "syscall"
21
22         "golang.org/x/xerrors"
23 )
24
25 func init() {
26         startRemote = startRemotePosix
27         autoNetworkAddress = autoNetworkAddressPosix
28         verifyRemoteOwnership = verifyRemoteOwnershipPosix
29 }
30
31 func startRemotePosix(goplsPath string, args ...string) error {
32         cmd := exec.Command(goplsPath, args...)
33         cmd.SysProcAttr = &syscall.SysProcAttr{
34                 Setsid: true,
35         }
36         if err := cmd.Start(); err != nil {
37                 return xerrors.Errorf("starting remote gopls: %w", err)
38         }
39         return nil
40 }
41
42 // autoNetworkAddress resolves an id on the 'auto' pseduo-network to a
43 // real network and address. On unix, this uses unix domain sockets.
44 func autoNetworkAddressPosix(goplsPath, id string) (network string, address string) {
45         // Especially when doing local development or testing, it's important that
46         // the remote gopls instance we connect to is running the same binary as our
47         // forwarder. So we encode a short hash of the binary path into the daemon
48         // socket name. If possible, we also include the buildid in this hash, to
49         // account for long-running processes where the binary has been subsequently
50         // rebuilt.
51         h := sha256.New()
52         cmd := exec.Command("go", "tool", "buildid", goplsPath)
53         cmd.Stdout = h
54         var pathHash []byte
55         if err := cmd.Run(); err == nil {
56                 pathHash = h.Sum(nil)
57         } else {
58                 log.Printf("error getting current buildid: %v", err)
59                 sum := sha256.Sum256([]byte(goplsPath))
60                 pathHash = sum[:]
61         }
62         shortHash := fmt.Sprintf("%x", pathHash)[:6]
63         user := os.Getenv("USER")
64         if user == "" {
65                 user = "shared"
66         }
67         basename := filepath.Base(goplsPath)
68         idComponent := ""
69         if id != "" {
70                 idComponent = "-" + id
71         }
72         runtimeDir := os.TempDir()
73         if xdg := os.Getenv("XDG_RUNTIME_DIR"); xdg != "" {
74                 runtimeDir = xdg
75         }
76         return "unix", filepath.Join(runtimeDir, fmt.Sprintf("%s-%s-daemon.%s%s", basename, shortHash, user, idComponent))
77 }
78
79 func verifyRemoteOwnershipPosix(network, address string) (bool, error) {
80         if network != "unix" {
81                 return true, nil
82         }
83         fi, err := os.Stat(address)
84         if err != nil {
85                 if os.IsNotExist(err) {
86                         return true, nil
87                 }
88                 return false, xerrors.Errorf("checking socket owner: %w", err)
89         }
90         stat, ok := fi.Sys().(*syscall.Stat_t)
91         if !ok {
92                 return false, errors.New("fi.Sys() is not a Stat_t")
93         }
94         user, err := user.Current()
95         if err != nil {
96                 return false, xerrors.Errorf("checking current user: %w", err)
97         }
98         uid, err := strconv.ParseUint(user.Uid, 10, 32)
99         if err != nil {
100                 return false, xerrors.Errorf("parsing current UID: %w", err)
101         }
102         return stat.Uid == uint32(uid), nil
103 }