]> Cypherpunks repositories - gostls13.git/commitdiff
os: use GetTempPath2 on Windows if available
authorThanonchai W <nontkrub@gmail.com>
Fri, 27 Jan 2023 05:54:48 +0000 (05:54 +0000)
committerQuim Muntal <quimmuntal@gmail.com>
Sat, 28 Jan 2023 19:27:04 +0000 (19:27 +0000)
This generates GetTempPath2. Go now tries to determine if the windows it runs on has GetTempPath2 by finding it only once at the loading time. If GetTempPath2 exists, it sets the flag so that any calls to tempDir will use it. If it doesn't exist, Go then uses GetTempPath.

GetTempPath2 was generated into internal/syscall/windows since syscall is locked down.

Fixes #56899

Change-Id: Iff08502aebc787fde802ee9496c070c982fbdc08
GitHub-Last-Rev: b77938953404b4e8e11f829c742e3eb109580c5e
GitHub-Pull-Request: golang/go#57980
Reviewed-on: https://go-review.googlesource.com/c/go/+/463219
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Reviewed-by: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
src/internal/syscall/windows/syscall_windows.go
src/internal/syscall/windows/zsyscall_windows.go
src/os/file_windows.go

index 311d083f45c14014343afebfc6a1c0c0736bb9ea..672ed63922281db1024b1dfcbf67121edc8b7341 100644 (file)
@@ -151,6 +151,7 @@ const (
 //sys  GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32, err error) = kernel32.GetModuleFileNameW
 //sys  SetFileInformationByHandle(handle syscall.Handle, fileInformationClass uint32, buf uintptr, bufsize uint32) (err error) = kernel32.SetFileInformationByHandle
 //sys  VirtualQuery(address uintptr, buffer *MemoryBasicInformation, length uintptr) (err error) = kernel32.VirtualQuery
+//sys  GetTempPath2(buflen uint32, buf *uint16) (n uint32, err error) = GetTempPath2W
 
 const (
        // flags for CreateToolhelp32Snapshot
@@ -363,6 +364,10 @@ func LoadGetFinalPathNameByHandle() error {
        return procGetFinalPathNameByHandleW.Find()
 }
 
+func ErrorLoadingGetTempPath2() error {
+       return procGetTempPath2W.Find()
+}
+
 //sys  CreateEnvironmentBlock(block **uint16, token syscall.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock
 //sys  DestroyEnvironmentBlock(block *uint16) (err error) = userenv.DestroyEnvironmentBlock
 
index fd2f255b9b4f9146b1c90b483b5d6e2c79b02f33..1b5a0c045e1f53778d76c4f8458ff73e027168fd 100644 (file)
@@ -62,6 +62,7 @@ var (
        procGetFinalPathNameByHandleW     = modkernel32.NewProc("GetFinalPathNameByHandleW")
        procGetModuleFileNameW            = modkernel32.NewProc("GetModuleFileNameW")
        procGetVolumeInformationByHandleW = modkernel32.NewProc("GetVolumeInformationByHandleW")
+       procGetTempPath2W                 = modkernel32.NewProc("GetTempPath2W")
        procLockFileEx                    = modkernel32.NewProc("LockFileEx")
        procModule32FirstW                = modkernel32.NewProc("Module32FirstW")
        procModule32NextW                 = modkernel32.NewProc("Module32NextW")
@@ -220,6 +221,15 @@ func GetModuleFileName(module syscall.Handle, fn *uint16, len uint32) (n uint32,
        return
 }
 
+func GetTempPath2(buflen uint32, buf *uint16) (n uint32, err error) {
+       r0, _, e1 := syscall.Syscall(procGetTempPath2W.Addr(), 2, uintptr(buflen), uintptr(unsafe.Pointer(buf)), 0)
+       n = uint32(r0)
+       if n == 0 {
+               err = errnoErr(e1)
+       }
+       return
+}
+
 func GetVolumeInformationByHandle(file syscall.Handle, volumeNameBuffer *uint16, volumeNameSize uint32, volumeNameSerialNumber *uint32, maximumComponentLength *uint32, fileSystemFlags *uint32, fileSystemNameBuffer *uint16, fileSystemNameSize uint32) (err error) {
        r1, _, e1 := syscall.Syscall9(procGetVolumeInformationByHandleW.Addr(), 8, uintptr(file), uintptr(unsafe.Pointer(volumeNameBuffer)), uintptr(volumeNameSize), uintptr(unsafe.Pointer(volumeNameSerialNumber)), uintptr(unsafe.Pointer(maximumComponentLength)), uintptr(unsafe.Pointer(fileSystemFlags)), uintptr(unsafe.Pointer(fileSystemNameBuffer)), uintptr(fileSystemNameSize), 0)
        if r1 == 0 {
index a48feca855a3afa58131dab8f3cf75fab62cb92e..e7ee3a56071f6d763fc57980edd69ebae23d4724 100644 (file)
@@ -9,6 +9,7 @@ import (
        "internal/poll"
        "internal/syscall/windows"
        "runtime"
+       "sync"
        "syscall"
        "unicode/utf16"
        "unsafe"
@@ -230,11 +231,23 @@ func Pipe() (r *File, w *File, err error) {
        return newFile(p[0], "|0", "pipe"), newFile(p[1], "|1", "pipe"), nil
 }
 
+var (
+       useGetTempPath2Once sync.Once
+       useGetTempPath2     bool
+)
+
 func tempDir() string {
+       useGetTempPath2Once.Do(func() {
+               useGetTempPath2 = (windows.ErrorLoadingGetTempPath2() == nil)
+       })
+       getTempPath := syscall.GetTempPath
+       if useGetTempPath2 {
+               getTempPath = windows.GetTempPath2
+       }
        n := uint32(syscall.MAX_PATH)
        for {
                b := make([]uint16, n)
-               n, _ = syscall.GetTempPath(uint32(len(b)), &b[0])
+               n, _ = getTempPath(uint32(len(b)), &b[0])
                if n > uint32(len(b)) {
                        continue
                }