From: qmuntal Date: Fri, 23 Feb 2024 13:01:34 +0000 (+0100) Subject: os: avoid GetFileInformationByHandleEx call when stat'ing files on Windows X-Git-Tag: go1.23rc1~1103 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=49319ed5c7aa6de6dd4313887dc1494ae73439e2;p=gostls13.git os: avoid GetFileInformationByHandleEx call when stat'ing files on Windows os.Stat and os.Lstat on Windows use GetFileInformationByHandleEx to retrieve file information for reparse points and files that GetFileAttributesEx does not handle. However, GetFileInformationByHandleEx is only necessary for reparse points, so we can avoid the call for regular files. With this change we can drop the FAT hack that was added in CL 154377, as files won't have the FILE_ATTRIBUTE_REPARSE_POINT attribute set on that file system. Change-Id: Id18639067a6c3fa1bb2c6706d5b79358c224fe37 Reviewed-on: https://go-review.googlesource.com/c/go/+/566397 Reviewed-by: Carlos Amedee Reviewed-by: Alex Brainman LUCI-TryBot-Result: Go LUCI Reviewed-by: Bryan Mills --- diff --git a/src/os/types_windows.go b/src/os/types_windows.go index 7343355696..a23dee7064 100644 --- a/src/os/types_windows.go +++ b/src/os/types_windows.go @@ -48,18 +48,14 @@ func newFileStatFromGetFileInformationByHandle(path string, h syscall.Handle) (f return nil, &PathError{Op: "GetFileInformationByHandle", Path: path, Err: err} } - var ti windows.FILE_ATTRIBUTE_TAG_INFO - err = windows.GetFileInformationByHandleEx(h, windows.FileAttributeTagInfo, (*byte)(unsafe.Pointer(&ti)), uint32(unsafe.Sizeof(ti))) - if err != nil { - if errno, ok := err.(syscall.Errno); ok && errno == windows.ERROR_INVALID_PARAMETER { - // It appears calling GetFileInformationByHandleEx with - // FILE_ATTRIBUTE_TAG_INFO fails on FAT file system with - // ERROR_INVALID_PARAMETER. Clear ti.ReparseTag in that - // instance to indicate no symlinks are possible. - ti.ReparseTag = 0 - } else { + var reparseTag uint32 + if d.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 { + var ti windows.FILE_ATTRIBUTE_TAG_INFO + err = windows.GetFileInformationByHandleEx(h, windows.FileAttributeTagInfo, (*byte)(unsafe.Pointer(&ti)), uint32(unsafe.Sizeof(ti))) + if err != nil { return nil, &PathError{Op: "GetFileInformationByHandleEx", Path: path, Err: err} } + reparseTag = ti.ReparseTag } return &fileStat{ @@ -73,7 +69,7 @@ func newFileStatFromGetFileInformationByHandle(path string, h syscall.Handle) (f vol: d.VolumeSerialNumber, idxhi: d.FileIndexHigh, idxlo: d.FileIndexLow, - ReparseTag: ti.ReparseTag, + ReparseTag: reparseTag, // fileStat.path is used by os.SameFile to decide if it needs // to fetch vol, idxhi and idxlo. But these are already set, // so set fileStat.path to "" to prevent os.SameFile doing it again.