github.com/roboticscm/goman@v0.0.0-20210203095141-87c07b4a0a55/src/path/filepath/symlink_windows.go (about) 1 // Copyright 2012 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 package filepath 6 7 import ( 8 "syscall" 9 ) 10 11 func toShort(path string) (string, error) { 12 p, err := syscall.UTF16FromString(path) 13 if err != nil { 14 return "", err 15 } 16 b := p // GetShortPathName says we can reuse buffer 17 n, err := syscall.GetShortPathName(&p[0], &b[0], uint32(len(b))) 18 if err != nil { 19 return "", err 20 } 21 if n > uint32(len(b)) { 22 b = make([]uint16, n) 23 n, err = syscall.GetShortPathName(&p[0], &b[0], uint32(len(b))) 24 if err != nil { 25 return "", err 26 } 27 } 28 return syscall.UTF16ToString(b), nil 29 } 30 31 func toLong(path string) (string, error) { 32 p, err := syscall.UTF16FromString(path) 33 if err != nil { 34 return "", err 35 } 36 b := p // GetLongPathName says we can reuse buffer 37 n, err := syscall.GetLongPathName(&p[0], &b[0], uint32(len(b))) 38 if err != nil { 39 return "", err 40 } 41 if n > uint32(len(b)) { 42 b = make([]uint16, n) 43 n, err = syscall.GetLongPathName(&p[0], &b[0], uint32(len(b))) 44 if err != nil { 45 return "", err 46 } 47 } 48 b = b[:n] 49 return syscall.UTF16ToString(b), nil 50 } 51 52 func evalSymlinks(path string) (string, error) { 53 path, err := walkSymlinks(path) 54 if err != nil { 55 return "", err 56 } 57 58 p, err := toShort(path) 59 if err != nil { 60 return "", err 61 } 62 p, err = toLong(p) 63 if err != nil { 64 return "", err 65 } 66 // syscall.GetLongPathName does not change the case of the drive letter, 67 // but the result of EvalSymlinks must be unique, so we have 68 // EvalSymlinks(`c:\a`) == EvalSymlinks(`C:\a`). 69 // Make drive letter upper case. 70 if len(p) >= 2 && p[1] == ':' && 'a' <= p[0] && p[0] <= 'z' { 71 p = string(p[0]+'A'-'a') + p[1:] 72 } 73 return Clean(p), nil 74 }