mirror of
https://github.com/golang/go
synced 2024-11-26 08:38:01 -07:00
os: use GetTempPath2 on Windows if available
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: b779389534
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>
This commit is contained in:
parent
915af1b7ce
commit
26fd1fba12
@ -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
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user