1// +build windows
2
3package winio
4
5import (
6	"os"
7	"runtime"
8	"unsafe"
9
10	"golang.org/x/sys/windows"
11)
12
13// FileBasicInfo contains file access time and file attributes information.
14type FileBasicInfo struct {
15	CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime
16	FileAttributes                                          uint32
17	pad                                                     uint32 // padding
18}
19
20// GetFileBasicInfo retrieves times and attributes for a file.
21func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
22	bi := &FileBasicInfo{}
23	if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
24		return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
25	}
26	runtime.KeepAlive(f)
27	return bi, nil
28}
29
30// SetFileBasicInfo sets times and attributes for a file.
31func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
32	if err := windows.SetFileInformationByHandle(windows.Handle(f.Fd()), windows.FileBasicInfo, (*byte)(unsafe.Pointer(bi)), uint32(unsafe.Sizeof(*bi))); err != nil {
33		return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
34	}
35	runtime.KeepAlive(f)
36	return nil
37}
38
39// FileStandardInfo contains extended information for the file.
40// FILE_STANDARD_INFO in WinBase.h
41// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_standard_info
42type FileStandardInfo struct {
43	AllocationSize, EndOfFile int64
44	NumberOfLinks             uint32
45	DeletePending, Directory  bool
46}
47
48// GetFileStandardInfo retrieves ended information for the file.
49func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) {
50	si := &FileStandardInfo{}
51	if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileStandardInfo, (*byte)(unsafe.Pointer(si)), uint32(unsafe.Sizeof(*si))); err != nil {
52		return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
53	}
54	runtime.KeepAlive(f)
55	return si, nil
56}
57
58// FileIDInfo contains the volume serial number and file ID for a file. This pair should be
59// unique on a system.
60type FileIDInfo struct {
61	VolumeSerialNumber uint64
62	FileID             [16]byte
63}
64
65// GetFileID retrieves the unique (volume, file ID) pair for a file.
66func GetFileID(f *os.File) (*FileIDInfo, error) {
67	fileID := &FileIDInfo{}
68	if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()), windows.FileIdInfo, (*byte)(unsafe.Pointer(fileID)), uint32(unsafe.Sizeof(*fileID))); err != nil {
69		return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
70	}
71	runtime.KeepAlive(f)
72	return fileID, nil
73}
74