...
Run Format

Source file src/os/stat_windows.go

Documentation: os

     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  	"syscall"
     9  )
    10  
    11  // isNulName returns true if name is NUL file name.
    12  // For example, it returns true for both "NUL" and "nul".
    13  func isNulName(name string) bool {
    14  	if len(name) != 3 {
    15  		return false
    16  	}
    17  	if name[0] != 'n' && name[0] != 'N' {
    18  		return false
    19  	}
    20  	if name[1] != 'u' && name[1] != 'U' {
    21  		return false
    22  	}
    23  	if name[2] != 'l' && name[2] != 'L' {
    24  		return false
    25  	}
    26  	return true
    27  }
    28  
    29  // Stat returns the FileInfo structure describing file.
    30  // If there is an error, it will be of type *PathError.
    31  func (file *File) Stat() (FileInfo, error) {
    32  	if file == nil {
    33  		return nil, ErrInvalid
    34  	}
    35  
    36  	if file.isdir() {
    37  		// I don't know any better way to do that for directory
    38  		return Stat(file.dirinfo.path)
    39  	}
    40  	if isNulName(file.name) {
    41  		return &devNullStat, nil
    42  	}
    43  
    44  	ft, err := file.pfd.GetFileType()
    45  	if err != nil {
    46  		return nil, &PathError{"GetFileType", file.name, err}
    47  	}
    48  	switch ft {
    49  	case syscall.FILE_TYPE_PIPE, syscall.FILE_TYPE_CHAR:
    50  		return &fileStat{name: basename(file.name), filetype: ft}, nil
    51  	}
    52  
    53  	fs, err := newFileStatFromGetFileInformationByHandle(file.name, file.pfd.Sysfd)
    54  	if err != nil {
    55  		return nil, err
    56  	}
    57  	fs.filetype = ft
    58  	return fs, err
    59  }
    60  
    61  // statNolog implements Stat for Windows.
    62  func statNolog(name string) (FileInfo, error) {
    63  	if len(name) == 0 {
    64  		return nil, &PathError{"Stat", name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}
    65  	}
    66  	if isNulName(name) {
    67  		return &devNullStat, nil
    68  	}
    69  	namep, err := syscall.UTF16PtrFromString(fixLongPath(name))
    70  	if err != nil {
    71  		return nil, &PathError{"Stat", name, err}
    72  	}
    73  	fs, err := newFileStatFromGetFileAttributesExOrFindFirstFile(name, namep)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	if !fs.isSymlink() {
    78  		err = fs.updatePathAndName(name)
    79  		if err != nil {
    80  			return nil, err
    81  		}
    82  		return fs, nil
    83  	}
    84  	// Use Windows I/O manager to dereference the symbolic link, as per
    85  	// https://blogs.msdn.microsoft.com/oldnewthing/20100212-00/?p=14963/
    86  	h, err := syscall.CreateFile(namep, 0, 0, nil,
    87  		syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0)
    88  	if err != nil {
    89  		return nil, &PathError{"CreateFile", name, err}
    90  	}
    91  	defer syscall.CloseHandle(h)
    92  
    93  	return newFileStatFromGetFileInformationByHandle(name, h)
    94  }
    95  
    96  // lstatNolog implements Lstat for Windows.
    97  func lstatNolog(name string) (FileInfo, error) {
    98  	if len(name) == 0 {
    99  		return nil, &PathError{"Lstat", name, syscall.Errno(syscall.ERROR_PATH_NOT_FOUND)}
   100  	}
   101  	if isNulName(name) {
   102  		return &devNullStat, nil
   103  	}
   104  	namep, err := syscall.UTF16PtrFromString(fixLongPath(name))
   105  	if err != nil {
   106  		return nil, &PathError{"Lstat", name, err}
   107  	}
   108  	fs, err := newFileStatFromGetFileAttributesExOrFindFirstFile(name, namep)
   109  	if err != nil {
   110  		return nil, err
   111  	}
   112  	err = fs.updatePathAndName(name)
   113  	if err != nil {
   114  		return nil, err
   115  	}
   116  	return fs, nil
   117  }
   118  

View as plain text