aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Brainman <alex.brainman@gmail.com>2012-03-27 15:53:08 +1100
committerAlex Brainman <alex.brainman@gmail.com>2012-03-27 15:53:08 +1100
commit7a3965417426e4405a6ec81ce486668fa5c36e36 (patch)
treec878d62256237c8e6f48cf6df4eaf94a300fa6e6
parentd6c9af6a4ec531369340e51cb008da514477ef17 (diff)
downloadgo-7a3965417426e4405a6ec81ce486668fa5c36e36.tar.gz
go-7a3965417426e4405a6ec81ce486668fa5c36e36.zip
path/filepath: use windows GetShortPathName api to force GetLongPathName to do its work
R=golang-dev, rsc CC=golang-dev https://golang.org/cl/5928043
-rw-r--r--api/go1.txt2
-rw-r--r--src/pkg/path/filepath/symlink_windows.go38
-rw-r--r--src/pkg/syscall/syscall_windows.go1
-rw-r--r--src/pkg/syscall/zsyscall_windows_386.go14
-rw-r--r--src/pkg/syscall/zsyscall_windows_amd64.go14
5 files changed, 64 insertions, 5 deletions
diff --git a/api/go1.txt b/api/go1.txt
index d6372314af..e6bdd173e9 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 2d4257720e..2b5d1fc681 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 b0c24cca69..47209da8fe 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 093c4768f2..8e6afcf0a8 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 d298b7451f..c6ff6fe02e 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)