github.com/sean-/go@v0.0.0-20151219100004-97f854cd7bb6/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 path, err := walkSymlinks(path) 51 if err != nil { 52 return "", err 53 } 54 p, err := toShort(path) 55 if err != nil { 56 return "", err 57 } 58 p, err = toLong(p) 59 if err != nil { 60 return "", err 61 } 62 // syscall.GetLongPathName does not change the case of the drive letter, 63 // but the result of EvalSymlinks must be unique, so we have 64 // EvalSymlinks(`c:\a`) == EvalSymlinks(`C:\a`). 65 // Make drive letter upper case. 66 if len(p) >= 2 && p[1] == ':' && 'a' <= p[0] && p[0] <= 'z' { 67 p = string(p[0]+'A'-'a') + p[1:] 68 } 69 return Clean(p), nil 70 }