1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
|
package times
import (
"os"
"syscall"
"time"
"unsafe"
)
type timespecEx struct {
atime
mtime
ctime
btime
}
// StatFile finds a Windows Timespec with ChangeTime.
func StatFile(file *os.File) (Timespec, error) {
return statFile(syscall.Handle(file.Fd()))
}
func statFile(h syscall.Handle) (Timespec, error) {
var fileInfo fileBasicInfo
if err := getFileInformationByHandleEx(h, &fileInfo); err != nil {
return nil, err
}
var t timespecEx
t.atime.v = time.Unix(0, fileInfo.LastAccessTime.Nanoseconds())
t.mtime.v = time.Unix(0, fileInfo.LastWriteTime.Nanoseconds())
t.ctime.v = time.Unix(0, fileInfo.ChangeTime.Nanoseconds())
t.btime.v = time.Unix(0, fileInfo.CreationTime.Nanoseconds())
return t, nil
}
const hasPlatformSpecificStat = true
func platformSpecficStat(name string) (Timespec, error) {
if findProcErr != nil {
return nil, findProcErr
}
pathp, e := syscall.UTF16PtrFromString(name)
if e != nil {
return nil, e
}
h, e := syscall.CreateFile(pathp,
syscall.FILE_WRITE_ATTRIBUTES, syscall.FILE_SHARE_WRITE, nil,
syscall.OPEN_EXISTING, syscall.FILE_FLAG_BACKUP_SEMANTICS, 0)
if e != nil {
return nil, e
}
defer syscall.Close(h)
return statFile(h)
}
var (
findProcErr error
procGetFileInformationByHandleEx *syscall.Proc
)
func init() {
var modkernel32 *syscall.DLL
if modkernel32, findProcErr = syscall.LoadDLL("kernel32.dll"); findProcErr == nil {
procGetFileInformationByHandleEx, findProcErr = modkernel32.FindProc("GetFileInformationByHandleEx")
}
}
// fileBasicInfo holds the C++ data for FileTimes.
//
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa364217(v=vs.85).aspx
type fileBasicInfo struct {
CreationTime syscall.Filetime
LastAccessTime syscall.Filetime
LastWriteTime syscall.Filetime
ChangeTime syscall.Filetime
FileAttributes uint32
_ uint32 // padding
}
type fileInformationClass int
const (
fileBasicInfoClass fileInformationClass = iota
)
func getFileInformationByHandleEx(handle syscall.Handle, data *fileBasicInfo) (err error) {
if findProcErr != nil {
return findProcErr
}
r1, _, e1 := syscall.Syscall6(procGetFileInformationByHandleEx.Addr(), 4, uintptr(handle), uintptr(fileBasicInfoClass), uintptr(unsafe.Pointer(data)), unsafe.Sizeof(*data), 0, 0)
if r1 == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
}
return
}
|