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