Skip to content

Commit

Permalink
os: fix windows Lstat missing name for some files
Browse files Browse the repository at this point in the history
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 <alex.brainman@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
  • Loading branch information
cuonglm authored and alexbrainman committed Mar 20, 2019
1 parent e0181ff commit 9e0e9ac
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 10 deletions.
5 changes: 4 additions & 1 deletion src/os/os_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
16 changes: 7 additions & 9 deletions src/os/stat_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,22 +80,16 @@ 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,
LastWriteTime: fa.LastWriteTime,
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
Expand All @@ -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.
Expand Down
15 changes: 15 additions & 0 deletions src/os/types_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 9e0e9ac

Please sign in to comment.