diff --git a/api/go1.txt b/api/go1.txt index d6372314aff..e6bdd173e92 100644 --- a/api/go1.txt +++ b/api/go1.txt @@ -22244,6 +22244,7 @@ pkg syscall (windows-386), func GetProcessTimes(Handle, *Filetime, *Filetime, *F pkg syscall (windows-386), func GetProtoByName(string) (*Protoent, error) pkg syscall (windows-386), func GetQueuedCompletionStatus(Handle, *uint32, *uint32, **Overlapped, uint32) error pkg syscall (windows-386), func GetServByName(string, string) (*Servent, error) +pkg syscall (windows-386), func GetShortPathName(*uint16, *uint16, uint32) (uint32, error) pkg syscall (windows-386), func GetStartupInfo(*StartupInfo) error pkg syscall (windows-386), func GetStdHandle(int) (Handle, error) pkg syscall (windows-386), func GetSystemTimeAsFileTime(*Filetime) @@ -23161,6 +23162,7 @@ pkg syscall (windows-amd64), func GetProcessTimes(Handle, *Filetime, *Filetime, pkg syscall (windows-amd64), func GetProtoByName(string) (*Protoent, error) pkg syscall (windows-amd64), func GetQueuedCompletionStatus(Handle, *uint32, *uint32, **Overlapped, uint32) error pkg syscall (windows-amd64), func GetServByName(string, string) (*Servent, error) +pkg syscall (windows-amd64), func GetShortPathName(*uint16, *uint16, uint32) (uint32, error) pkg syscall (windows-amd64), func GetStartupInfo(*StartupInfo) error pkg syscall (windows-amd64), func GetStdHandle(int) (Handle, error) pkg syscall (windows-amd64), func GetSystemTimeAsFileTime(*Filetime) diff --git a/src/pkg/path/filepath/symlink_windows.go b/src/pkg/path/filepath/symlink_windows.go index 2d4257720e0..2b5d1fc681b 100644 --- a/src/pkg/path/filepath/symlink_windows.go +++ b/src/pkg/path/filepath/symlink_windows.go @@ -8,7 +8,24 @@ import ( "syscall" ) -func evalSymlinks(path string) (string, error) { +func toShort(path string) (string, error) { + p := syscall.StringToUTF16(path) + 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) { p := syscall.StringToUTF16(path) b := p // GetLongPathName says we can reuse buffer n, err := syscall.GetLongPathName(&p[0], &b[0], uint32(len(b))) @@ -23,13 +40,24 @@ func evalSymlinks(path string) (string, error) { } } b = b[:n] - s := syscall.UTF16ToString(b) + 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. This matches what os.Getwd returns. - if len(s) >= 2 && s[1] == ':' && 'a' <= s[0] && s[0] <= 'z' { - s = string(s[0]+'A'-'a') + s[1:] + if len(p) >= 2 && p[1] == ':' && 'a' <= p[0] && p[0] <= 'z' { + p = string(p[0]+'A'-'a') + p[1:] } - return Clean(s), nil + return Clean(p), nil } diff --git a/src/pkg/syscall/syscall_windows.go b/src/pkg/syscall/syscall_windows.go index b0c24cca698..47209da8fec 100644 --- a/src/pkg/syscall/syscall_windows.go +++ b/src/pkg/syscall/syscall_windows.go @@ -175,6 +175,7 @@ func NewCallback(fn interface{}) uintptr //sys FlushFileBuffers(handle Handle) (err error) //sys GetFullPathName(path *uint16, buflen uint32, buf *uint16, fname **uint16) (n uint32, err error) = kernel32.GetFullPathNameW //sys GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err error) = kernel32.GetLongPathNameW +//sys GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) = kernel32.GetShortPathNameW //sys CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) = kernel32.CreateFileMappingW //sys MapViewOfFile(handle Handle, access uint32, offsetHigh uint32, offsetLow uint32, length uintptr) (addr uintptr, err error) //sys UnmapViewOfFile(addr uintptr) (err error) diff --git a/src/pkg/syscall/zsyscall_windows_386.go b/src/pkg/syscall/zsyscall_windows_386.go index 093c4768f2f..8e6afcf0a85 100644 --- a/src/pkg/syscall/zsyscall_windows_386.go +++ b/src/pkg/syscall/zsyscall_windows_386.go @@ -79,6 +79,7 @@ var ( procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers") procGetFullPathNameW = modkernel32.NewProc("GetFullPathNameW") procGetLongPathNameW = modkernel32.NewProc("GetLongPathNameW") + procGetShortPathNameW = modkernel32.NewProc("GetShortPathNameW") procCreateFileMappingW = modkernel32.NewProc("CreateFileMappingW") procMapViewOfFile = modkernel32.NewProc("MapViewOfFile") procUnmapViewOfFile = modkernel32.NewProc("UnmapViewOfFile") @@ -904,6 +905,19 @@ func GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err er return } +func GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) { + r0, _, e1 := Syscall(procGetShortPathNameW.Addr(), 3, uintptr(unsafe.Pointer(longpath)), uintptr(unsafe.Pointer(shortpath)), uintptr(buflen)) + n = uint32(r0) + if n == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = EINVAL + } + } + return +} + func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) { r0, _, e1 := Syscall6(procCreateFileMappingW.Addr(), 6, uintptr(fhandle), uintptr(unsafe.Pointer(sa)), uintptr(prot), uintptr(maxSizeHigh), uintptr(maxSizeLow), uintptr(unsafe.Pointer(name))) handle = Handle(r0) diff --git a/src/pkg/syscall/zsyscall_windows_amd64.go b/src/pkg/syscall/zsyscall_windows_amd64.go index d298b7451fd..c6ff6fe02e2 100644 --- a/src/pkg/syscall/zsyscall_windows_amd64.go +++ b/src/pkg/syscall/zsyscall_windows_amd64.go @@ -79,6 +79,7 @@ var ( procFlushFileBuffers = modkernel32.NewProc("FlushFileBuffers") procGetFullPathNameW = modkernel32.NewProc("GetFullPathNameW") procGetLongPathNameW = modkernel32.NewProc("GetLongPathNameW") + procGetShortPathNameW = modkernel32.NewProc("GetShortPathNameW") procCreateFileMappingW = modkernel32.NewProc("CreateFileMappingW") procMapViewOfFile = modkernel32.NewProc("MapViewOfFile") procUnmapViewOfFile = modkernel32.NewProc("UnmapViewOfFile") @@ -904,6 +905,19 @@ func GetLongPathName(path *uint16, buf *uint16, buflen uint32) (n uint32, err er return } +func GetShortPathName(longpath *uint16, shortpath *uint16, buflen uint32) (n uint32, err error) { + r0, _, e1 := Syscall(procGetShortPathNameW.Addr(), 3, uintptr(unsafe.Pointer(longpath)), uintptr(unsafe.Pointer(shortpath)), uintptr(buflen)) + n = uint32(r0) + if n == 0 { + if e1 != 0 { + err = error(e1) + } else { + err = EINVAL + } + } + return +} + func CreateFileMapping(fhandle Handle, sa *SecurityAttributes, prot uint32, maxSizeHigh uint32, maxSizeLow uint32, name *uint16) (handle Handle, err error) { r0, _, e1 := Syscall6(procCreateFileMappingW.Addr(), 6, uintptr(fhandle), uintptr(unsafe.Pointer(sa)), uintptr(prot), uintptr(maxSizeHigh), uintptr(maxSizeLow), uintptr(unsafe.Pointer(name))) handle = Handle(r0)