github.com/muesli/go@v0.0.0-20170208044820-e410d2a81ef2/src/os/types_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 "sync" 9 "syscall" 10 "time" 11 ) 12 13 // A fileStat is the implementation of FileInfo returned by Stat and Lstat. 14 type fileStat struct { 15 name string 16 sys syscall.Win32FileAttributeData 17 filetype uint32 // what syscall.GetFileType returns 18 19 // used to implement SameFile 20 sync.Mutex 21 path string 22 vol uint32 23 idxhi uint32 24 idxlo uint32 25 } 26 27 func (fs *fileStat) Size() int64 { 28 return int64(fs.sys.FileSizeHigh)<<32 + int64(fs.sys.FileSizeLow) 29 } 30 31 func (fs *fileStat) Mode() (m FileMode) { 32 if fs == &devNullStat { 33 return ModeDevice | ModeCharDevice | 0666 34 } 35 if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_DIRECTORY != 0 { 36 m |= ModeDir | 0111 37 } 38 if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_READONLY != 0 { 39 m |= 0444 40 } else { 41 m |= 0666 42 } 43 if fs.sys.FileAttributes&syscall.FILE_ATTRIBUTE_REPARSE_POINT != 0 { 44 m |= ModeSymlink 45 } 46 switch fs.filetype { 47 case syscall.FILE_TYPE_PIPE: 48 m |= ModeNamedPipe 49 case syscall.FILE_TYPE_CHAR: 50 m |= ModeCharDevice 51 } 52 return m 53 } 54 55 func (fs *fileStat) ModTime() time.Time { 56 return time.Unix(0, fs.sys.LastWriteTime.Nanoseconds()) 57 } 58 59 // Sys returns syscall.Win32FileAttributeData for file fs. 60 func (fs *fileStat) Sys() interface{} { return &fs.sys } 61 62 func (fs *fileStat) loadFileId() error { 63 fs.Lock() 64 defer fs.Unlock() 65 if fs.path == "" { 66 // already done 67 return nil 68 } 69 pathp, err := syscall.UTF16PtrFromString(fs.path) 70 if err != nil { 71 return err 72 } 73 h, err := syscall.CreateFile(pathp, 0, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0) 74 if err != nil { 75 return err 76 } 77 defer syscall.CloseHandle(h) 78 var i syscall.ByHandleFileInformation 79 err = syscall.GetFileInformationByHandle(h, &i) 80 if err != nil { 81 return err 82 } 83 fs.path = "" 84 fs.vol = i.VolumeSerialNumber 85 fs.idxhi = i.FileIndexHigh 86 fs.idxlo = i.FileIndexLow 87 return nil 88 } 89 90 // devNullStat is fileStat structure describing DevNull file ("NUL"). 91 var devNullStat = fileStat{ 92 name: DevNull, 93 // hopefully this will work for SameFile 94 vol: 0, 95 idxhi: 0, 96 idxlo: 0, 97 } 98 99 func sameFile(fs1, fs2 *fileStat) bool { 100 e := fs1.loadFileId() 101 if e != nil { 102 return false 103 } 104 e = fs2.loadFileId() 105 if e != nil { 106 return false 107 } 108 return fs1.vol == fs2.vol && fs1.idxhi == fs2.idxhi && fs1.idxlo == fs2.idxlo 109 } 110 111 // For testing. 112 func atime(fi FileInfo) time.Time { 113 return time.Unix(0, fi.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds()) 114 }