2012-03-30 23:27:11 +02:00
|
|
|
// Copyright 2012 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
package filepath
|
|
|
|
|
|
|
|
import (
|
|
|
|
"syscall"
|
|
|
|
)
|
|
|
|
|
2012-03-31 00:36:44 +02:00
|
|
|
func toShort(path string) (string, error) {
|
2012-10-23 06:31:11 +02:00
|
|
|
p, err := syscall.UTF16FromString(path)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2012-03-31 00:36:44 +02:00
|
|
|
b := p // GetShortPathName says we can reuse buffer
|
|
|
|
n, err := syscall.GetShortPathName(&p[0], &b[0], uint32(len(b)))
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
if n > uint32(len(b)) {
|
|
|
|
b = make([]uint16, n)
|
|
|
|
n, err = syscall.GetShortPathName(&p[0], &b[0], uint32(len(b)))
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return syscall.UTF16ToString(b), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func toLong(path string) (string, error) {
|
2012-10-23 06:31:11 +02:00
|
|
|
p, err := syscall.UTF16FromString(path)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2012-03-30 23:27:11 +02:00
|
|
|
b := p // GetLongPathName says we can reuse buffer
|
|
|
|
n, err := syscall.GetLongPathName(&p[0], &b[0], uint32(len(b)))
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
if n > uint32(len(b)) {
|
|
|
|
b = make([]uint16, n)
|
|
|
|
n, err = syscall.GetLongPathName(&p[0], &b[0], uint32(len(b)))
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
b = b[:n]
|
2012-03-31 00:36:44 +02:00
|
|
|
return syscall.UTF16ToString(b), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func evalSymlinks(path string) (string, error) {
|
|
|
|
p, err := toShort(path)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
p, err = toLong(p)
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
// syscall.GetLongPathName does not change the case of the drive letter,
|
|
|
|
// but the result of EvalSymlinks must be unique, so we have
|
|
|
|
// EvalSymlinks(`c:\a`) == EvalSymlinks(`C:\a`).
|
|
|
|
// Make drive letter upper case.
|
|
|
|
if len(p) >= 2 && p[1] == ':' && 'a' <= p[0] && p[0] <= 'z' {
|
|
|
|
p = string(p[0]+'A'-'a') + p[1:]
|
|
|
|
}
|
|
|
|
return Clean(p), nil
|
2012-03-30 23:27:11 +02:00
|
|
|
}
|