]> Cypherpunks repositories - gostls13.git/commitdiff
io/ioutil.TempFile for Windows
authorPeter Mundy <go.peter.90@gmail.com>
Wed, 30 Jun 2010 20:52:34 +0000 (13:52 -0700)
committerRuss Cox <rsc@golang.org>
Wed, 30 Jun 2010 20:52:34 +0000 (13:52 -0700)
Fixes #834.

R=rsc, brainman
CC=golang-dev
https://golang.org/cl/1686047

src/pkg/io/ioutil/tempfile.go
src/pkg/io/ioutil/tempfile_test.go
src/pkg/os/Makefile
src/pkg/os/env_unix.go [new file with mode: 0755]
src/pkg/os/env_windows.go [new file with mode: 0755]
src/pkg/syscall/syscall_windows.go
src/pkg/syscall/zsyscall_windows_386.go

index 55fcf47026df721d0daf894b5410c9bf0b3613ea..114eca2b50e40134b6e016d7b35f0f8dc52e7aa7 100644 (file)
@@ -33,18 +33,15 @@ func nextSuffix() string {
 // TempFile creates a new temporary file in the directory dir
 // with a name beginning with prefix, opens the file for reading
 // and writing, and returns the resulting *os.File.
-// If dir is the empty string, TempFile uses the value of the
-// environment variable $TMPDIR or, if that is empty,/tmp.
+// If dir is the empty string, TempFile uses the default directory
+// for temporary files (see os.TempDir).
 // Multiple programs calling TempFile simultaneously
 // will not choose the same file.  The caller can use f.Name()
 // to find the name of the file.  It is the caller's responsibility to
 // remove the file when no longer needed.
 func TempFile(dir, prefix string) (f *os.File, err os.Error) {
        if dir == "" {
-               dir = os.Getenv("TMPDIR")
-               if dir == "" {
-                       dir = "/tmp"
-               }
+               dir = os.TempDir()
        }
 
        nconflict := 0
index fbe45dc6dd6413ad75371fcb441c2a9dbb51c29b..fe43f956685d4145cf375838f8c2f1e017fa334b 100644 (file)
@@ -7,6 +7,7 @@ package ioutil_test
 import (
        . "io/ioutil"
        "os"
+       "regexp"
        "testing"
 )
 
@@ -16,14 +17,17 @@ func TestTempFile(t *testing.T) {
                t.Errorf("TempFile(`/_not_exists_`, `foo`) = %v, %v", f, err)
        }
 
-       f, err = TempFile("/tmp", "ioutil_test")
+       dir := os.TempDir()
+       f, err = TempFile(dir, "ioutil_test")
        if f == nil || err != nil {
-               t.Errorf("TempFile(`/tmp`, `ioutil_test`) = %v, %v", f, err)
+               t.Errorf("TempFile(dir, `ioutil_test`) = %v, %v", f, err)
        }
-       re := testing.MustCompile("^/tmp/ioutil_test[0-9]+$")
-       if !re.MatchString(f.Name()) {
-               t.Fatalf("TempFile(`/tmp`, `ioutil_test`) created bad name %s", f.Name())
+       if f != nil {
+               re := testing.MustCompile("^" + regexp.QuoteMeta(dir) + "/ioutil_test[0-9]+$")
+               if !re.MatchString(f.Name()) {
+                       t.Errorf("TempFile(`"+dir+"`, `ioutil_test`) created bad name %s", f.Name())
+               }
+               os.Remove(f.Name())
        }
-       os.Remove(f.Name())
        f.Close()
 }
index 71de94951472e76eebe75e61a62e6a98c6b19e8e..45954bbeb81104e65e8db6478429a1f40cd43870 100644 (file)
@@ -19,22 +19,27 @@ GOFILES=\
        types.go\
 
 GOFILES_freebsd=\
+       env_unix.go\
        file_unix.go\
        sys_bsd.go\
 
 GOFILES_darwin=\
+       env_unix.go\
        file_unix.go\
        sys_bsd.go\
 
 GOFILES_linux=\
+       env_unix.go\
        file_unix.go\
        sys_linux.go\
 
 GOFILES_nacl=\
+       env_unix.go\
        file_unix.go\
        sys_nacl.go\
 
 GOFILES_windows=\
+       env_windows.go\
        file_windows.go\
        sys_windows.go\
 
diff --git a/src/pkg/os/env_unix.go b/src/pkg/os/env_unix.go
new file mode 100755 (executable)
index 0000000..0c13bda
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2010 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.
+
+// Unix environment variables.
+
+package os
+
+// TempDir returns the default directory to use for temporary files.
+// On Unix-like systems, it uses the environment variable $TMPDIR
+// or, if that is empty, /tmp.
+// On Windows systems, it uses the Windows GetTempPath API.
+func TempDir() string {
+       dir := Getenv("TMPDIR")
+       if dir == "" {
+               dir = "/tmp"
+       }
+       return dir
+}
diff --git a/src/pkg/os/env_windows.go b/src/pkg/os/env_windows.go
new file mode 100755 (executable)
index 0000000..7d5b007
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2010 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.
+
+// Windows environment variables.
+
+package os
+
+import (
+       "syscall"
+       "utf16"
+)
+
+func TempDir() string {
+       const pathSep = '\\'
+       dirw := make([]uint16, syscall.MAX_PATH)
+       n, _ := syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
+       if n > uint32(len(dirw)) {
+               dirw = make([]uint16, n)
+               n, _ = syscall.GetTempPath(uint32(len(dirw)), &dirw[0])
+               if n > uint32(len(dirw)) {
+                       n = 0
+               }
+       }
+       if n > 0 && dirw[n-1] == pathSep {
+               n--
+       }
+       return string(utf16.Decode(dirw[0:n]))
+}
index 8b6789221bbffefd29f30391bdafae68e8aaa25e..86badb8e939033198edd34bb01f22c6cbc37a722 100644 (file)
@@ -131,6 +131,7 @@ func getSysProcAddr(m uint32, pname string) uintptr {
 //sys  GetTimeZoneInformation(tzi *Timezoneinformation) (rc uint32, errno int) [failretval=0xffffffff]
 //sys  CreateIoCompletionPort(filehandle int32, cphandle int32, key uint32, threadcnt uint32) (handle int32, errno int)
 //sys  GetQueuedCompletionStatus(cphandle int32, qty *uint32, key *uint32, overlapped **Overlapped, timeout uint32) (ok bool, errno int)
+//sys  GetTempPath(buflen uint32, buf *uint16) (n uint32, errno int) = GetTempPathW
 
 // syscall interface implementation for other packages
 
index 306de3031abe5655f6e7e03e2f9e80171feeb10e..be5dd031c80db9709a0a47eb0ca4b0cea4a1cb24 100644 (file)
@@ -40,6 +40,7 @@ var (
        procGetTimeZoneInformation     = getSysProcAddr(modkernel32, "GetTimeZoneInformation")
        procCreateIoCompletionPort     = getSysProcAddr(modkernel32, "CreateIoCompletionPort")
        procGetQueuedCompletionStatus  = getSysProcAddr(modkernel32, "GetQueuedCompletionStatus")
+       procGetTempPathW               = getSysProcAddr(modkernel32, "GetTempPathW")
        procWSAStartup                 = getSysProcAddr(modwsock32, "WSAStartup")
        procWSACleanup                 = getSysProcAddr(modwsock32, "WSACleanup")
        procsocket                     = getSysProcAddr(modwsock32, "socket")
@@ -375,6 +376,17 @@ func GetQueuedCompletionStatus(cphandle int32, qty *uint32, key *uint32, overlap
        return
 }
 
+func GetTempPath(buflen uint32, buf *uint16) (n uint32, errno int) {
+       r0, _, e1 := Syscall(procGetTempPathW, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0)
+       n = uint32(r0)
+       if n == 0 {
+               errno = int(e1)
+       } 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)