From 9e0e9ac5547a9cc5174cca79abaac0cdd3ec787e Mon Sep 17 00:00:00 2001 From: LE Manh Cuong Date: Sun, 17 Mar 2019 11:56:29 +0700 Subject: [PATCH] os: fix windows Lstat missing name for some files On Windows, GetFileAttributesEx fails with ERROR_SHARING_VIOLATION for some files, like c:\pagefile.sys. In this case, newFileStatFromWin32finddata is used to fill file info, but it does not fill name and path. After getting file stat from newFileStatFromWin32finddata, just set file info name and path before return fixes the issue. Fixes #30883 Change-Id: I654e96c634e8a9bf5ce7e1aaa93968e88953620d Reviewed-on: https://go-review.googlesource.com/c/go/+/167779 Run-TryBot: Alex Brainman TryBot-Result: Gobot Gobot Reviewed-by: Alex Brainman --- src/os/os_windows_test.go | 5 ++++- src/os/stat_windows.go | 16 +++++++--------- src/os/types_windows.go | 15 +++++++++++++++ 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/os/os_windows_test.go b/src/os/os_windows_test.go index 0b42e089bd..326670cc9d 100644 --- a/src/os/os_windows_test.go +++ b/src/os/os_windows_test.go @@ -755,8 +755,11 @@ func TestReadStdin(t *testing.T) { } func TestStatPagefile(t *testing.T) { - _, err := os.Stat(`c:\pagefile.sys`) + fi, err := os.Stat(`c:\pagefile.sys`) if err == nil { + if fi.Name() == "" { + t.Fatal(`FileInfo of c:\pagefile.sys has empty name`) + } return } if os.IsNotExist(err) { diff --git a/src/os/stat_windows.go b/src/os/stat_windows.go index 271ff5f843..fd22ef21ab 100644 --- a/src/os/stat_windows.go +++ b/src/os/stat_windows.go @@ -80,7 +80,6 @@ func stat(funcname, name string, createFileAttrs uint32) (FileInfo, error) { if err == nil && fa.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 { // Not a symlink. fs := &fileStat{ - path: name, FileAttributes: fa.FileAttributes, CreationTime: fa.CreationTime, LastAccessTime: fa.LastAccessTime, @@ -88,14 +87,9 @@ func stat(funcname, name string, createFileAttrs uint32) (FileInfo, error) { FileSizeHigh: fa.FileSizeHigh, FileSizeLow: fa.FileSizeLow, } - // Gather full path to be used by os.SameFile later. - if !isAbs(fs.path) { - fs.path, err = syscall.FullPath(fs.path) - if err != nil { - return nil, &PathError{"FullPath", name, err} - } + if err := fs.saveInfoFromPath(name); err != nil { + return nil, err } - fs.name = basename(name) return fs, nil } // GetFileAttributesEx fails with ERROR_SHARING_VIOLATION error for @@ -107,7 +101,11 @@ func stat(funcname, name string, createFileAttrs uint32) (FileInfo, error) { return nil, &PathError{"FindFirstFile", name, err} } syscall.FindClose(sh) - return newFileStatFromWin32finddata(&fd), nil + fs := newFileStatFromWin32finddata(&fd) + if err := fs.saveInfoFromPath(name); err != nil { + return nil, err + } + return fs, nil } // Finally use CreateFile. diff --git a/src/os/types_windows.go b/src/os/types_windows.go index 5e33292bec..3d1a6674b1 100644 --- a/src/os/types_windows.go +++ b/src/os/types_windows.go @@ -189,6 +189,21 @@ func (fs *fileStat) loadFileId() error { return nil } +// saveInfoFromPath saves full path of the file to be used by os.SameFile later, +// and set name from path. +func (fs *fileStat) saveInfoFromPath(path string) error { + fs.path = path + if !isAbs(fs.path) { + var err error + fs.path, err = syscall.FullPath(fs.path) + if err != nil { + return &PathError{"FullPath", path, err} + } + } + fs.name = basename(path) + return nil +} + // devNullStat is fileStat structure describing DevNull file ("NUL"). var devNullStat = fileStat{ name: DevNull, -- 2.48.1