...
Source file
src/path/filepath/symlink_windows.go
1
2
3
4
5 package filepath
6
7 import (
8 "strings"
9 "syscall"
10 )
11
12
13
14
15 func normVolumeName(path string) string {
16 volume := VolumeName(path)
17
18 if len(volume) > 2 {
19 return volume
20 }
21
22 return strings.ToUpper(volume)
23 }
24
25
26 func normBase(path string) (string, error) {
27 p, err := syscall.UTF16PtrFromString(path)
28 if err != nil {
29 return "", err
30 }
31
32 var data syscall.Win32finddata
33
34 h, err := syscall.FindFirstFile(p, &data)
35 if err != nil {
36 return "", err
37 }
38 syscall.FindClose(h)
39
40 return syscall.UTF16ToString(data.FileName[:]), nil
41 }
42
43
44
45 func baseIsDotDot(path string) bool {
46 i := strings.LastIndexByte(path, Separator)
47 return path[i+1:] == ".."
48 }
49
50
51
52
53
54
55
56
57
58
59
60
61 func toNorm(path string, normBase func(string) (string, error)) (string, error) {
62 if path == "" {
63 return path, nil
64 }
65
66 volume := normVolumeName(path)
67 path = path[len(volume):]
68
69
70 if path == "" || path == "." || path == `\` {
71 return volume + path, nil
72 }
73
74 var normPath string
75
76 for {
77 if baseIsDotDot(path) {
78 normPath = path + `\` + normPath
79
80 break
81 }
82
83 name, err := normBase(volume + path)
84 if err != nil {
85 return "", err
86 }
87
88 normPath = name + `\` + normPath
89
90 i := strings.LastIndexByte(path, Separator)
91 if i == -1 {
92 break
93 }
94 if i == 0 {
95 normPath = `\` + normPath
96
97 break
98 }
99
100 path = path[:i]
101 }
102
103 normPath = normPath[:len(normPath)-1]
104
105 return volume + normPath, nil
106 }
107
108 func evalSymlinks(path string) (string, error) {
109 newpath, err := walkSymlinks(path)
110 if err != nil {
111 return "", err
112 }
113 newpath, err = toNorm(newpath, normBase)
114 if err != nil {
115 return "", err
116 }
117 return newpath, nil
118 }
119
View as plain text