github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/os/stat_windows.go (about)

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package os
     6  
     7  import (
     8  	"internal/syscall/windows"
     9  	"syscall"
    10  	"unsafe"
    11  )
    12  
    13  // Stat returns the FileInfo structure describing file.
    14  // If there is an error, it will be of type *PathError.
    15  func (file *File) Stat() (FileInfo, error) {
    16  	if file == nil {
    17  		return nil, ErrInvalid
    18  	}
    19  	if file == nil || file.fd < 0 {
    20  		return nil, syscall.EINVAL
    21  	}
    22  	if file.isdir() {
    23  		// I don't know any better way to do that for directory
    24  		return Stat(file.dirinfo.path)
    25  	}
    26  	if file.name == DevNull {
    27  		return &devNullStat, nil
    28  	}
    29  
    30  	ft, err := syscall.GetFileType(file.fd)
    31  	if err != nil {
    32  		return nil, &PathError{"GetFileType", file.name, err}
    33  	}
    34  	if ft == syscall.FILE_TYPE_PIPE {
    35  		return &fileStat{name: basename(file.name), pipe: true}, nil
    36  	}
    37  
    38  	var d syscall.ByHandleFileInformation
    39  	err = syscall.GetFileInformationByHandle(file.fd, &d)
    40  	if err != nil {
    41  		return nil, &PathError{"GetFileInformationByHandle", file.name, err}
    42  	}
    43  	return &fileStat{
    44  		name: basename(file.name),
    45  		sys: syscall.Win32FileAttributeData{
    46  			FileAttributes: d.FileAttributes,
    47  			CreationTime:   d.CreationTime,
    48  			LastAccessTime: d.LastAccessTime,
    49  			LastWriteTime:  d.LastWriteTime,
    50  			FileSizeHigh:   d.FileSizeHigh,
    51  			FileSizeLow:    d.FileSizeLow,
    52  		},
    53  		vol:   d.VolumeSerialNumber,
    54  		idxhi: d.FileIndexHigh,
    55  		idxlo: d.FileIndexLow,
    56  		pipe:  false,
    57  	}, nil
    58  }
    59  
    60  // Stat returns a FileInfo structure describing the named file.
    61  // If there is an error, it will be of type *PathError.
    62  func Stat(name string) (FileInfo, error) {
    63  	var fi FileInfo
    64  	var err error
    65  	for i := 0; i < 255; i++ {
    66  		fi, err = Lstat(name)
    67  		if err != nil {
    68  			return fi, err
    69  		}
    70  		if fi.Mode()&ModeSymlink == 0 {
    71  			return fi, nil
    72  		}
    73  		name, err = Readlink(name)
    74  		if err != nil {
    75  			return fi, err
    76  		}
    77  	}
    78  	return nil, &PathError{"Stat", name, syscall.ELOOP}
    79  }
    80  
    81  // Lstat returns the FileInfo structure describing the named file.
    82  // If the file is a symbolic link, the returned FileInfo
    83  // describes the symbolic link. Lstat makes no attempt to follow the link.
    84  // If there is an error, it will be of type *PathError.
    85  func Lstat(name string) (FileInfo, error) {
    86  	if len(name) == 0 {
    87  		return nil, &PathError{"Lstat", name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}
    88  	}
    89  	if name == DevNull {
    90  		return &devNullStat, nil
    91  	}
    92  	fs := &fileStat{name: basename(name)}
    93  	namep, e := syscall.UTF16PtrFromString(fixLongPath(name))
    94  	if e != nil {
    95  		return nil, &PathError{"Lstat", name, e}
    96  	}
    97  	e = syscall.GetFileAttributesEx(namep, syscall.GetFileExInfoStandard, (*byte)(unsafe.Pointer(&fs.sys)))
    98  	if e != nil {
    99  		if e != windows.ERROR_SHARING_VIOLATION {
   100  			return nil, &PathError{"GetFileAttributesEx", name, e}
   101  		}
   102  		// try FindFirstFile now that GetFileAttributesEx failed
   103  		var fd syscall.Win32finddata
   104  		h, e2 := syscall.FindFirstFile(namep, &fd)
   105  		if e2 != nil {
   106  			return nil, &PathError{"FindFirstFile", name, e}
   107  		}
   108  		syscall.FindClose(h)
   109  
   110  		fs.sys.FileAttributes = fd.FileAttributes
   111  		fs.sys.CreationTime = fd.CreationTime
   112  		fs.sys.LastAccessTime = fd.LastAccessTime
   113  		fs.sys.LastWriteTime = fd.LastWriteTime
   114  		fs.sys.FileSizeHigh = fd.FileSizeHigh
   115  		fs.sys.FileSizeLow = fd.FileSizeLow
   116  	}
   117  	fs.path = name
   118  	if !isAbs(fs.path) {
   119  		fs.path, e = syscall.FullPath(fs.path)
   120  		if e != nil {
   121  			return nil, e
   122  		}
   123  	}
   124  	return fs, nil
   125  }