github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/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 return m 43 } 44 45 func (fs *fileStat) ModTime() time.Time { 46 return time.Unix(0, fs.sys.LastWriteTime.Nanoseconds()) 47 } 48 49 // Sys returns syscall.Win32FileAttributeData for file fs. 50 func (fs *fileStat) Sys() interface{} { return &fs.sys } 51 52 func (fs *fileStat) loadFileId() error { 53 fs.Lock() 54 defer fs.Unlock() 55 if fs.path == "" { 56 // already done 57 return nil 58 } 59 pathp, err := syscall.UTF16PtrFromString(fs.path) 60 if err != nil { 61 return err 62 } 63 h, err := syscall.CreateFile(pathp, 0, 0, nil, syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0) 64 if err != nil { 65 return err 66 } 67 defer syscall.CloseHandle(h) 68 var i syscall.ByHandleFileInformation 69 err = syscall.GetFileInformationByHandle(syscall.Handle(h), &i) 70 if err != nil { 71 return err 72 } 73 fs.path = "" 74 fs.vol = i.VolumeSerialNumber 75 fs.idxhi = i.FileIndexHigh 76 fs.idxlo = i.FileIndexLow 77 return nil 78 } 79 80 // devNullStat is fileStat structure describing DevNull file ("NUL"). 81 var devNullStat = fileStat{ 82 name: DevNull, 83 // hopefully this will work for SameFile 84 vol: 0, 85 idxhi: 0, 86 idxlo: 0, 87 } 88 89 func sameFile(fs1, fs2 *fileStat) bool { 90 e := fs1.loadFileId() 91 if e != nil { 92 return false 93 } 94 e = fs2.loadFileId() 95 if e != nil { 96 return false 97 } 98 return fs1.vol == fs2.vol && fs1.idxhi == fs2.idxhi && fs1.idxlo == fs2.idxlo 99 } 100 101 // For testing. 102 func atime(fi FileInfo) time.Time { 103 return time.Unix(0, fi.Sys().(*syscall.Win32FileAttributeData).LastAccessTime.Nanoseconds()) 104 }