github.com/fjballest/golang@v0.0.0-20151209143359-e4c5fe594ca8/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 := uint32(len(b)) 18 for { 19 n, err = syscall.GetShortPathName(&p[0], &b[0], uint32(len(b))) 20 if err != nil { 21 return "", err 22 } 23 if n <= uint32(len(b)) { 24 return syscall.UTF16ToString(b[:n]), nil 25 } 26 b = make([]uint16, n) 27 } 28 } 29 30 func toLong(path string) (string, error) { 31 p, err := syscall.UTF16FromString(path) 32 if err != nil { 33 return "", err 34 } 35 b := p // GetLongPathName says we can reuse buffer 36 n := uint32(len(b)) 37 for { 38 n, err = syscall.GetLongPathName(&p[0], &b[0], uint32(len(b))) 39 if err != nil { 40 return "", err 41 } 42 if n <= uint32(len(b)) { 43 return syscall.UTF16ToString(b[:n]), nil 44 } 45 b = make([]uint16, n) 46 } 47 } 48 49 func evalSymlinks(path string) (string, error) { 50 newpath, err := walkSymlinks(path) 51 if err != nil { 52 return "", err 53 } 54 // discard the walk if path is "." and link destination is relative path (just like unix does) 55 if path != "." || IsAbs(newpath) { 56 path = newpath 57 } 58 59 p, err := toShort(path) 60 if err != nil { 61 return "", err 62 } 63 p, err = toLong(p) 64 if err != nil { 65 return "", err 66 } 67 // syscall.GetLongPathName does not change the case of the drive letter, 68 // but the result of EvalSymlinks must be unique, so we have 69 // EvalSymlinks(`c:\a`) == EvalSymlinks(`C:\a`). 70 // Make drive letter upper case. 71 if len(p) >= 2 && p[1] == ':' && 'a' <= p[0] && p[0] <= 'z' { 72 p = string(p[0]+'A'-'a') + p[1:] 73 } 74 return Clean(p), nil 75 }