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 func toNorm(path string, normBase func(string) (string, error)) (string, error) {
61 if path == "" {
62 return path, nil
63 }
64
65 path = Clean(path)
66
67 volume := normVolumeName(path)
68 path = path[len(volume):]
69
70
71 if path == "" || path == "." || path == `\` {
72 return volume + path, nil
73 }
74
75 var normPath string
76
77 for {
78 if baseIsDotDot(path) {
79 normPath = path + `\` + normPath
80
81 break
82 }
83
84 name, err := normBase(volume + path)
85 if err != nil {
86 return "", err
87 }
88
89 normPath = name + `\` + normPath
90
91 i := strings.LastIndexByte(path, Separator)
92 if i == -1 {
93 break
94 }
95 if i == 0 {
96 normPath = `\` + normPath
97
98 break
99 }
100
101 path = path[:i]
102 }
103
104 normPath = normPath[:len(normPath)-1]
105
106 return volume + normPath, nil
107 }
108
109 func evalSymlinks(path string) (string, error) {
110 newpath, err := walkSymlinks(path)
111 if err != nil {
112 return "", err
113 }
114 newpath, err = toNorm(newpath, normBase)
115 if err != nil {
116 return "", err
117 }
118 return newpath, nil
119 }
120
View as plain text