1
0
mirror of https://github.com/golang/go synced 2024-11-17 05:35:00 -07:00

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 <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>
This commit is contained in:
qmuntal 2024-02-23 14:01:34 +01:00 committed by Quim Muntal
parent f7777688ca
commit 49319ed5c7

View 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.