| // Copyright 2009 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package os | |
| import ( | |
| "internal/syscall/windows" | |
| "syscall" | |
| "unsafe" | |
| ) | |
| // Stat returns the FileInfo structure describing file. | |
| // If there is an error, it will be of type *PathError. | |
| func (file *File) Stat() (FileInfo, error) { | |
| if file == nil { | |
| return nil, ErrInvalid | |
| } | |
| if file.isdir() { | |
| // I don't know any better way to do that for directory | |
| return Stat(file.dirinfo.path) | |
| } | |
| if isWindowsNulName(file.name) { | |
| return &devNullStat, nil | |
| } | |
| ft, err := file.pfd.GetFileType() | |
| if err != nil { | |
| return nil, &PathError{Op: "GetFileType", Path: file.name, Err: err} | |
| } | |
| switch ft { | |
| case syscall.FILE_TYPE_PIPE, syscall.FILE_TYPE_CHAR: | |
| return &fileStat{name: basename(file.name), filetype: ft}, nil | |
| } | |
| fs, err := newFileStatFromGetFileInformationByHandle(file.name, file.pfd.Sysfd) | |
| if err != nil { | |
| return nil, err | |
| } | |
| fs.filetype = ft | |
| return fs, err | |
| } | |
| // stat implements both Stat and Lstat of a file. | |
| func stat(funcname, name string, createFileAttrs uint32) (FileInfo, error) { | |
| if len(name) == 0 { | |
| return nil, &PathError{Op: funcname, Path: name, Err: syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)} | |
| } | |
| if isWindowsNulName(name) { | |
| return &devNullStat, nil | |
| } | |
| namep, err := syscall.UTF16PtrFromString(fixLongPath(name)) | |
| if err != nil { | |
| return nil, &PathError{Op: funcname, Path: name, Err: err} | |
| } | |
| // Try GetFileAttributesEx first, because it is faster than CreateFile. | |
| // See https://golang.org/issues/19922#issuecomment-300031421 for details. | |
| var fa syscall.Win32FileAttributeData | |
| err = syscall.GetFileAttributesEx(namep, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fa))) | |
| if err == nil && fa.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT == 0 { | |
| // Not a symlink. | |
| fs := &fileStat{ | |
| FileAttributes: fa.FileAttributes, | |
| CreationTime: fa.CreationTime, | |
| LastAccessTime: fa.LastAccessTime, | |
| LastWriteTime: fa.LastWriteTime, | |
| FileSizeHigh: fa.FileSizeHigh, | |
| FileSizeLow: fa.FileSizeLow, | |
| } | |
| if err := fs.saveInfoFromPath(name); err != nil { | |
| return nil, err | |
| } | |
| return fs, nil | |
| } | |
| // GetFileAttributesEx fails with ERROR_SHARING_VIOLATION error for | |
| // files, like c:\pagefile.sys. Use FindFirstFile for such files. | |
| if err == windows.ERROR_SHARING_VIOLATION { | |
| var fd syscall.Win32finddata | |
| sh, err := syscall.FindFirstFile(namep, &fd) | |
| if err != nil { | |
| return nil, &PathError{Op: "FindFirstFile", Path: name, Err: err} | |
| } | |
| syscall.FindClose(sh) | |
| fs := newFileStatFromWin32finddata(&fd) | |
| if err := fs.saveInfoFromPath(name); err != nil { | |
| return nil, err | |
| } | |
| return fs, nil | |
| } | |
| // Finally use CreateFile. | |
| h, err := syscall.CreateFile(namep, 0, 0, nil, | |
| syscall.OPEN_EXISTING, createFileAttrs, 0) | |
| if err != nil { | |
| return nil, &PathError{Op: "CreateFile", Path: name, Err: err} | |
| } | |
| defer syscall.CloseHandle(h) | |
| return newFileStatFromGetFileInformationByHandle(name, h) | |
| } | |
| // statNolog implements Stat for Windows. | |
| func statNolog(name string) (FileInfo, error) { | |
| return stat("Stat", name, syscall.FILE_FLAG_BACKUP_SEMANTICS) | |
| } | |
| // lstatNolog implements Lstat for Windows. | |
| func lstatNolog(name string) (FileInfo, error) { | |
| attrs := uint32(syscall.FILE_FLAG_BACKUP_SEMANTICS) | |
| // Use FILE_FLAG_OPEN_REPARSE_POINT, otherwise CreateFile will follow symlink. | |
| // See https://docs.microsoft.com/en-us/windows/desktop/FileIO/symbolic-link-effects-on-file-systems-functions#createfile-and-createfiletransacted | |
| attrs |= syscall.FILE_FLAG_OPEN_REPARSE_POINT | |
| return stat("Lstat", name, attrs) | |
| } |