Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / internal / lsp / cache / os_windows.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 package cache
5
6 import (
7         "fmt"
8         "path/filepath"
9         "syscall"
10 )
11
12 func init() {
13         checkPathCase = windowsCheckPathCase
14 }
15
16 func windowsCheckPathCase(path string) error {
17         // Back in the day, Windows used to have short and long filenames, and
18         // it still supports those APIs. GetLongPathName gets the real case for a
19         // path, so we can use it here. Inspired by
20         // http://stackoverflow.com/q/2113822.
21
22         // Short paths can be longer than long paths, and unicode, so be generous.
23         buflen := 4 * len(path)
24         namep, err := syscall.UTF16PtrFromString(path)
25         if err != nil {
26                 return err
27         }
28         short := make([]uint16, buflen)
29         n, err := syscall.GetShortPathName(namep, &short[0], uint32(len(short)*2)) // buflen is in bytes.
30         if err != nil {
31                 return err
32         }
33         if int(n) > len(short)*2 {
34                 return fmt.Errorf("short buffer too short: %v vs %v*2", n, len(short))
35         }
36         long := make([]uint16, buflen)
37         n, err = syscall.GetLongPathName(&short[0], &long[0], uint32(len(long)*2))
38         if err != nil {
39                 return err
40         }
41         if int(n) > len(long)*2 {
42                 return fmt.Errorf("long buffer too short: %v vs %v*2", n, len(long))
43         }
44         longstr := syscall.UTF16ToString(long)
45
46         isRoot := func(p string) bool {
47                 return p[len(p)-1] == filepath.Separator
48         }
49         for got, want := path, longstr; !isRoot(got) && !isRoot(want); got, want = filepath.Dir(got), filepath.Dir(want) {
50                 if g, w := filepath.Base(got), filepath.Base(want); g != w {
51                         return fmt.Errorf("case mismatch in path %q: component %q should be %q", path, g, w)
52                 }
53         }
54         return nil
55 }