]> Cypherpunks repositories - gostls13.git/commitdiff
os: avoid GetFileInformationByHandleEx call when stat'ing files on Windows
authorqmuntal <quimmuntal@gmail.com>
Fri, 23 Feb 2024 13:01:34 +0000 (14:01 +0100)
committerQuim Muntal <quimmuntal@gmail.com>
Tue, 27 Feb 2024 16:41:24 +0000 (16:41 +0000)
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 <carlos@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
src/os/types_windows.go

index 73433556968d92b178dfb2e9a3b5f9aff0d7c9fc..a23dee7064bdefaf4b6d6e6bb829cef55c822654 100644 (file)
@@ -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.