1// +build windows
2
3package winio
4
5import (
6	"os"
7	"runtime"
8	"syscall"
9	"unsafe"
10)
11
12//sys getFileInformationByHandleEx(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = GetFileInformationByHandleEx
13//sys setFileInformationByHandle(h syscall.Handle, class uint32, buffer *byte, size uint32) (err error) = SetFileInformationByHandle
14
15const (
16	fileBasicInfo = 0
17	fileIDInfo    = 0x12
18)
19
20// FileBasicInfo contains file access time and file attributes information.
21type FileBasicInfo struct {
22	CreationTime, LastAccessTime, LastWriteTime, ChangeTime syscall.Filetime
23	FileAttributes                                          uint32
24	pad                                                     uint32 // padding
25}
26
27// GetFileBasicInfo retrieves times and attributes for a file.
28func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
29	bi := &FileBasicInfo{}
30	if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
31		return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
32	}
33	runtime.KeepAlive(f)
34	return bi, nil
35}
36
37// SetFileBasicInfo sets times and attributes for a file.
38func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
39	if err := setFileInformationByHandle(syscall.Handle(f.Fd()), fileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
40		return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
41	}
42	runtime.KeepAlive(f)
43	return nil
44}
45
46// FileIDInfo contains the volume serial number and file ID for a file. This pair should be
47// unique on a system.
48type FileIDInfo struct {
49	VolumeSerialNumber uint64
50	FileID             [16]byte
51}
52
53// GetFileID retrieves the unique (volume, file ID) pair for a file.
54func GetFileID(f *os.File) (*FileIDInfo, error) {
55	fileID := &FileIDInfo{}
56	if err := getFileInformationByHandleEx(syscall.Handle(f.Fd()), fileIDInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil {
57		return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
58	}
59	runtime.KeepAlive(f)
60	return fileID, nil
61}
62