...
1
2
3 package shimdiag
4
5 import (
6 fmt "fmt"
7 "os"
8 "path/filepath"
9 "sort"
10 strings "strings"
11
12 "github.com/Microsoft/go-winio"
13 "github.com/containerd/ttrpc"
14 "golang.org/x/sys/windows"
15 )
16
17 const (
18 shimPrefix = `\\.\pipe\ProtectedPrefix\Administrators\containerd-shim-`
19 shimSuffix = `-pipe`
20 )
21
22 func findPipes(pattern string) ([]string, error) {
23 path := `\\.\pipe\*`
24 path16, err := windows.UTF16FromString(path)
25 if err != nil {
26 return nil, err
27 }
28 var data windows.Win32finddata
29 h, err := windows.FindFirstFile(&path16[0], &data)
30 if err != nil {
31 return nil, &os.PathError{Op: "FindFirstFile", Path: path, Err: err}
32 }
33 var names []string
34 for {
35 name := `\\.\pipe\` + windows.UTF16ToString(data.FileName[:])
36 if matched, _ := filepath.Match(pattern, name); matched {
37 names = append(names, name)
38 }
39 err = windows.FindNextFile(h, &data)
40 if err == windows.ERROR_NO_MORE_FILES {
41 break
42 }
43 if err != nil {
44 return nil, &os.PathError{Op: "FindNextFile", Path: path, Err: err}
45 }
46 }
47 return names, nil
48 }
49
50 func FindShims(name string) ([]string, error) {
51 pipes, err := findPipes(shimPrefix + name + "*" + shimSuffix)
52 if err != nil {
53 return nil, err
54 }
55 for i, p := range pipes {
56 pipes[i] = p[len(shimPrefix) : len(p)-len(shimSuffix)]
57 }
58 sort.Strings(pipes)
59 return pipes, nil
60 }
61
62 func findShim(name string) (string, error) {
63 if strings.ContainsAny(name, "*?\\/") {
64 return "", fmt.Errorf("invalid shim name %s", name)
65 }
66 shims, err := FindShims(name)
67 if err != nil {
68 return "", err
69 }
70 if len(shims) == 0 {
71 return "", fmt.Errorf("no such shim %s", name)
72 }
73 if len(shims) > 1 && shims[0] != name {
74 return "", fmt.Errorf("multiple shims beginning with %s", name)
75 }
76 return shims[0], nil
77 }
78
79 func GetShim(name string) (*ttrpc.Client, error) {
80 shim, err := findShim(name)
81 if err != nil {
82 return nil, err
83 }
84 conn, err := winio.DialPipe(shimPrefix+shim+shimSuffix, nil)
85 if err != nil {
86 return nil, err
87 }
88 return ttrpc.NewClient(conn), nil
89 }
90
View as plain text