go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/_motor/providers/winrm/cat/winstat.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package cat
     5  
     6  // this implementation is derived from golang's internal stat implementation
     7  // Golang licensed BSD-style license https://github.com/golang/go/blob/master/LICENSE
     8  // see  https://github.com/golang/go/blob/5d1a95175e693f5be0bc31ae9e6a7873318925eb/src/syscall/types_windows.go
     9  
    10  import (
    11  	"os"
    12  	"time"
    13  
    14  	"github.com/rs/zerolog/log"
    15  )
    16  
    17  const (
    18  	FILE_SHARE_READ              = 0x00000001
    19  	FILE_SHARE_WRITE             = 0x00000002
    20  	FILE_SHARE_DELETE            = 0x00000004
    21  	FILE_ATTRIBUTE_READONLY      = 0x00000001
    22  	FILE_ATTRIBUTE_HIDDEN        = 0x00000002
    23  	FILE_ATTRIBUTE_SYSTEM        = 0x00000004
    24  	FILE_ATTRIBUTE_DIRECTORY     = 0x00000010
    25  	FILE_ATTRIBUTE_ARCHIVE       = 0x00000020
    26  	FILE_ATTRIBUTE_NORMAL        = 0x00000080
    27  	FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400
    28  
    29  	INVALID_FILE_ATTRIBUTES = 0xffffffff
    30  
    31  	CREATE_NEW        = 1
    32  	CREATE_ALWAYS     = 2
    33  	OPEN_EXISTING     = 3
    34  	OPEN_ALWAYS       = 4
    35  	TRUNCATE_EXISTING = 5
    36  
    37  	FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
    38  	FILE_FLAG_BACKUP_SEMANTICS   = 0x02000000
    39  	FILE_FLAG_OVERLAPPED         = 0x40000000
    40  )
    41  
    42  const (
    43  	FSCTL_GET_REPARSE_POINT          = 0x900A8
    44  	MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 16 * 1024
    45  	_IO_REPARSE_TAG_MOUNT_POINT      = 0xA0000003
    46  	IO_REPARSE_TAG_SYMLINK           = 0xA000000C
    47  	SYMBOLIC_LINK_FLAG_DIRECTORY     = 0x1
    48  	_SYMLINK_FLAG_RELATIVE           = 1
    49  )
    50  
    51  const (
    52  	FILE_TYPE_CHAR    = 0x0002
    53  	FILE_TYPE_DISK    = 0x0001
    54  	FILE_TYPE_PIPE    = 0x0003
    55  	FILE_TYPE_REMOTE  = 0x8000
    56  	FILE_TYPE_UNKNOWN = 0x0000
    57  )
    58  
    59  const (
    60  	FSCTL_SET_REPARSE_POINT    = 0x000900A4
    61  	IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003
    62  	SYMLINK_FLAG_RELATIVE      = 1
    63  )
    64  
    65  type Win32FileAttributeData struct {
    66  	FileAttributes uint32
    67  	CreationTime   *time.Time
    68  	LastAccessTime *time.Time
    69  	LastWriteTime  *time.Time
    70  	FileSize       int64
    71  }
    72  
    73  // A fileStat is the implementation of FileInfo returned by Stat and Lstat.
    74  type fileStat struct {
    75  	name string
    76  
    77  	// from ByHandleFileInformation, Win32FileAttributeData and Win32finddata
    78  	FileAttributes uint32
    79  	CreationTime   *time.Time
    80  	LastAccessTime *time.Time
    81  	LastWriteTime  *time.Time
    82  	FileSize       int64
    83  
    84  	// from Win32finddata
    85  	Reserved0 uint32
    86  
    87  	// what syscall.GetFileType returns
    88  	filetype uint32
    89  }
    90  
    91  // devNullStat is fileStat structure describing DevNull file ("NUL").
    92  var devNullStat = fileStat{
    93  	name: os.DevNull,
    94  }
    95  
    96  func (fs *fileStat) Name() string { return fs.name }
    97  func (fs *fileStat) IsDir() bool  { return fs.Mode().IsDir() }
    98  
    99  func (fs *fileStat) isSymlink() bool {
   100  	// Use instructions described at
   101  	// https://blogs.msdn.microsoft.com/oldnewthing/20100212-00/?p=14963/
   102  	// to recognize whether it's a symlink.
   103  	if fs.FileAttributes&FILE_ATTRIBUTE_REPARSE_POINT == 0 {
   104  		return false
   105  	}
   106  	return fs.Reserved0 == IO_REPARSE_TAG_SYMLINK ||
   107  		fs.Reserved0 == IO_REPARSE_TAG_MOUNT_POINT
   108  }
   109  
   110  func (fs *fileStat) Size() int64 {
   111  	return fs.FileSize
   112  }
   113  
   114  func (fs *fileStat) Mode() (m os.FileMode) {
   115  	if fs == &devNullStat {
   116  		return os.ModeDevice | os.ModeCharDevice | 0666
   117  	}
   118  	if fs.FileAttributes&FILE_ATTRIBUTE_READONLY != 0 {
   119  		m |= 0444
   120  	} else {
   121  		m |= 0666
   122  	}
   123  	if fs.isSymlink() {
   124  		return m | os.ModeSymlink
   125  	}
   126  	if fs.FileAttributes&FILE_ATTRIBUTE_DIRECTORY != 0 {
   127  		m |= os.ModeDir | 0111
   128  	}
   129  	switch fs.filetype {
   130  	case FILE_TYPE_PIPE:
   131  		m |= os.ModeNamedPipe
   132  	case FILE_TYPE_CHAR:
   133  		m |= os.ModeDevice | os.ModeCharDevice
   134  	}
   135  	return m
   136  }
   137  
   138  func (fs *fileStat) ModTime() time.Time {
   139  	if fs.LastWriteTime != nil {
   140  		return *fs.LastWriteTime
   141  	}
   142  	log.Error().Str("file", fs.name).Msg("could not determine mod time")
   143  	return time.Time{}
   144  }
   145  
   146  // Sys returns Win32FileAttributeData for file fs.
   147  func (fs *fileStat) Sys() interface{} {
   148  	return &Win32FileAttributeData{
   149  		FileAttributes: fs.FileAttributes,
   150  		CreationTime:   fs.CreationTime,
   151  		LastAccessTime: fs.LastAccessTime,
   152  		LastWriteTime:  fs.LastWriteTime,
   153  		FileSize:       fs.FileSize,
   154  	}
   155  }