]> Cypherpunks repositories - gostls13.git/commitdiff
syscall: fix Stat(path) where path is directory with trailing '/' on windows
authorAlex Brainman <alex.brainman@gmail.com>
Sat, 30 Oct 2010 12:06:49 +0000 (23:06 +1100)
committerAlex Brainman <alex.brainman@gmail.com>
Sat, 30 Oct 2010 12:06:49 +0000 (23:06 +1100)
Fixes #1220.

R=rsc, r
CC=golang-dev
https://golang.org/cl/2728043

src/pkg/os/os_test.go
src/pkg/syscall/syscall_windows.go
src/pkg/syscall/zsyscall_windows_386.go
src/pkg/syscall/ztypes_windows_386.go

index eacb0f71f58aa30ec872c8fe4d41f2ab9458b8df..0bbb686e18253e2e7f49269a5020ba0cf0217cf3 100644 (file)
@@ -861,3 +861,27 @@ func TestAppend(t *testing.T) {
                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_")
+}
index d42103bc284ff1272000d03438427cfe3df73c72..049e9e29b3bd71fa9614acb49805f0ab1ae30d9d 100644 (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  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  GetFileAttributes(name *uint16) (attrs uint32, errno int) [failretval=INVALID_FILE_ATTRIBUTES] = kernel32.GetFileAttributesW
 
 // 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) {
+       // 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)
        if e != 0 {
                return e
index 292d0e32eac4885bb2a0f9e81007c95acdfb254f..6837de1208af4f017daead7031d5c67545ec5c31 100644 (file)
@@ -60,6 +60,7 @@ var (
        procGetEnvironmentVariableW    = getSysProcAddr(modkernel32, "GetEnvironmentVariableW")
        procSetEnvironmentVariableW    = getSysProcAddr(modkernel32, "SetEnvironmentVariableW")
        procSetFileTime                = getSysProcAddr(modkernel32, "SetFileTime")
+       procGetFileAttributesW         = getSysProcAddr(modkernel32, "GetFileAttributesW")
        procWSAStartup                 = getSysProcAddr(modwsock32, "WSAStartup")
        procWSACleanup                 = getSysProcAddr(modwsock32, "WSACleanup")
        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) {
        r0, _, e1 := Syscall(procOpenProcess, uintptr(da), uintptr(b), uintptr(pid))
-       handle = (uint32)(r0)
+       handle = uint32(r0)
        if handle == 0 {
                if e1 != 0 {
                        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) {
        r0, _, e1 := Syscall(procGetExitCodeProcess, uintptr(h), uintptr(unsafe.Pointer(c)), 0)
-       ok = (bool)(r0 != 0)
+       ok = bool(r0 != 0)
        if !ok {
                if e1 != 0 {
                        errno = int(e1)
@@ -786,6 +787,21 @@ func SetFileTime(handle int32, ctime *Filetime, atime *Filetime, wtime *Filetime
        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) {
        r0, _, _ := Syscall(procWSAStartup, uintptr(verreq), uintptr(unsafe.Pointer(data)), 0)
        sockerrno = int(r0)
index 4e54ee6cda517886e11beb3c5f8e2c50fc554db2..a874d9fc7a89f385c55497b50ff427e1c0da430a 100644 (file)
@@ -66,6 +66,8 @@ const (
        FILE_ATTRIBUTE_ARCHIVE   = 0x00000020
        FILE_ATTRIBUTE_NORMAL    = 0x00000080
 
+       INVALID_FILE_ATTRIBUTES = 0xffffffff
+
        CREATE_NEW        = 1
        CREATE_ALWAYS     = 2
        OPEN_EXISTING     = 3