mirror of
https://github.com/rclone/rclone.git
synced 2024-11-26 18:34:41 +01:00
97 lines
2.2 KiB
Go
97 lines
2.2 KiB
Go
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
|
|
}
|
|
|
|
f, err := os.Open(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer f.Close()
|
|
|
|
return statFile(syscall.Handle(f.Fd()))
|
|
}
|
|
|
|
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
|
|
}
|