1
0
mirror of https://github.com/golang/go synced 2024-11-22 04:24:39 -07:00

syscall: fix Stat(path) where path is directory with trailing '/' on windows

Fixes #1220.

R=rsc, r
CC=golang-dev
https://golang.org/cl/2728043
This commit is contained in:
Alex Brainman 2010-10-30 23:06:49 +11:00
parent edaeb88bd5
commit 7812b79627
4 changed files with 60 additions and 2 deletions

View File

@ -861,3 +861,27 @@ func TestAppend(t *testing.T) {
t.Fatalf("writeFile: have %q want %q", s, "new|append") t.Fatalf("writeFile: have %q want %q", s, "new|append")
} }
} }
func TestStatDirWithTrailingSlash(t *testing.T) {
// Create new dir, in _obj so it will get
// cleaned up by make if not by us.
path := "_obj/_TestStatDirWithSlash_"
err := MkdirAll(path, 0777)
if err != nil {
t.Fatalf("MkdirAll %q: %s", path, err)
}
// Stat of path should succeed.
_, err = Stat(path)
if err != nil {
t.Fatal("stat failed:", err)
}
// Stat of path+"/" should succeed too.
_, err = Stat(path + "/")
if err != nil {
t.Fatal("stat failed:", err)
}
RemoveAll("_obj/_TestMkdirAll_")
}

View File

@ -144,6 +144,7 @@ func getSysProcAddr(m uint32, pname string) uintptr {
//sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, errno int) = kernel32.GetEnvironmentVariableW //sys GetEnvironmentVariable(name *uint16, buffer *uint16, size uint32) (n uint32, errno int) = kernel32.GetEnvironmentVariableW
//sys SetEnvironmentVariable(name *uint16, value *uint16) (ok bool, errno int) = kernel32.SetEnvironmentVariableW //sys SetEnvironmentVariable(name *uint16, value *uint16) (ok bool, errno int) = kernel32.SetEnvironmentVariableW
//sys SetFileTime(handle int32, ctime *Filetime, atime *Filetime, wtime *Filetime) (ok bool, errno int) //sys SetFileTime(handle int32, ctime *Filetime, atime *Filetime, wtime *Filetime) (ok bool, errno int)
//sys GetFileAttributes(name *uint16) (attrs uint32, errno int) [failretval=INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW
// syscall interface implementation for other packages // syscall interface implementation for other packages
@ -302,6 +303,21 @@ func getStdHandle(h int32) (fd int) {
} }
func Stat(path string, stat *Stat_t) (errno int) { func Stat(path string, stat *Stat_t) (errno int) {
// Remove trailing slash.
if path[len(path)-1] == '/' || path[len(path)-1] == '\\' {
// Check if we're given root directory ("\" or "c:\").
if len(path) == 1 || (len(path) == 3 && path[1] == ':') {
// TODO(brainman): Perhaps should fetch other fields, not just FileAttributes.
stat.Windata = Win32finddata{}
a, e := GetFileAttributes(StringToUTF16Ptr(path))
if e != 0 {
return e
}
stat.Windata.FileAttributes = a
return 0
}
path = path[:len(path)-1]
}
h, e := FindFirstFile(StringToUTF16Ptr(path), &stat.Windata) h, e := FindFirstFile(StringToUTF16Ptr(path), &stat.Windata)
if e != 0 { if e != 0 {
return e return e

View File

@ -60,6 +60,7 @@ var (
procGetEnvironmentVariableW = getSysProcAddr(modkernel32, "GetEnvironmentVariableW") procGetEnvironmentVariableW = getSysProcAddr(modkernel32, "GetEnvironmentVariableW")
procSetEnvironmentVariableW = getSysProcAddr(modkernel32, "SetEnvironmentVariableW") procSetEnvironmentVariableW = getSysProcAddr(modkernel32, "SetEnvironmentVariableW")
procSetFileTime = getSysProcAddr(modkernel32, "SetFileTime") procSetFileTime = getSysProcAddr(modkernel32, "SetFileTime")
procGetFileAttributesW = getSysProcAddr(modkernel32, "GetFileAttributesW")
procWSAStartup = getSysProcAddr(modwsock32, "WSAStartup") procWSAStartup = getSysProcAddr(modwsock32, "WSAStartup")
procWSACleanup = getSysProcAddr(modwsock32, "WSACleanup") procWSACleanup = getSysProcAddr(modwsock32, "WSACleanup")
procsocket = getSysProcAddr(modwsock32, "socket") procsocket = getSysProcAddr(modwsock32, "socket")
@ -683,7 +684,7 @@ func CryptGenRandom(provhandle uint32, buflen uint32, buf *byte) (ok bool, errno
func OpenProcess(da uint32, b int, pid uint32) (handle uint32, errno int) { func OpenProcess(da uint32, b int, pid uint32) (handle uint32, errno int) {
r0, _, e1 := Syscall(procOpenProcess, uintptr(da), uintptr(b), uintptr(pid)) r0, _, e1 := Syscall(procOpenProcess, uintptr(da), uintptr(b), uintptr(pid))
handle = (uint32)(r0) handle = uint32(r0)
if handle == 0 { if handle == 0 {
if e1 != 0 { if e1 != 0 {
errno = int(e1) errno = int(e1)
@ -698,7 +699,7 @@ func OpenProcess(da uint32, b int, pid uint32) (handle uint32, errno int) {
func GetExitCodeProcess(h uint32, c *uint32) (ok bool, errno int) { func GetExitCodeProcess(h uint32, c *uint32) (ok bool, errno int) {
r0, _, e1 := Syscall(procGetExitCodeProcess, uintptr(h), uintptr(unsafe.Pointer(c)), 0) r0, _, e1 := Syscall(procGetExitCodeProcess, uintptr(h), uintptr(unsafe.Pointer(c)), 0)
ok = (bool)(r0 != 0) ok = bool(r0 != 0)
if !ok { if !ok {
if e1 != 0 { if e1 != 0 {
errno = int(e1) errno = int(e1)
@ -786,6 +787,21 @@ func SetFileTime(handle int32, ctime *Filetime, atime *Filetime, wtime *Filetime
return return
} }
func GetFileAttributes(name *uint16) (attrs uint32, errno int) {
r0, _, e1 := Syscall(procGetFileAttributesW, uintptr(unsafe.Pointer(name)), 0, 0)
attrs = uint32(r0)
if attrs == INVALID_FILE_ATTRIBUTES {
if e1 != 0 {
errno = int(e1)
} else {
errno = EINVAL
}
} else {
errno = 0
}
return
}
func WSAStartup(verreq uint32, data *WSAData) (sockerrno int) { func WSAStartup(verreq uint32, data *WSAData) (sockerrno int) {
r0, _, _ := Syscall(procWSAStartup, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0) r0, _, _ := Syscall(procWSAStartup, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
sockerrno = int(r0) sockerrno = int(r0)

View File

@ -66,6 +66,8 @@ const (
FILE_ATTRIBUTE_ARCHIVE = 0x00000020 FILE_ATTRIBUTE_ARCHIVE = 0x00000020
FILE_ATTRIBUTE_NORMAL = 0x00000080 FILE_ATTRIBUTE_NORMAL = 0x00000080
INVALID_FILE_ATTRIBUTES = 0xffffffff
CREATE_NEW = 1 CREATE_NEW = 1
CREATE_ALWAYS = 2 CREATE_ALWAYS = 2
OPEN_EXISTING = 3 OPEN_EXISTING = 3