main
1//go:build windows
2// +build windows
3
4package winio
5
6import (
7 "os"
8 "runtime"
9 "unsafe"
10
11 "golang.org/x/sys/windows"
12)
13
14// FileBasicInfo contains file access time and file attributes information.
15type FileBasicInfo struct {
16 CreationTime, LastAccessTime, LastWriteTime, ChangeTime windows.Filetime
17 FileAttributes uint32
18 _ uint32 // padding
19}
20
21// alignedFileBasicInfo is a FileBasicInfo, but aligned to uint64 by containing
22// uint64 rather than windows.Filetime. Filetime contains two uint32s. uint64
23// alignment is necessary to pass this as FILE_BASIC_INFO.
24type alignedFileBasicInfo struct {
25 CreationTime, LastAccessTime, LastWriteTime, ChangeTime uint64
26 FileAttributes uint32
27 _ uint32 // padding
28}
29
30// GetFileBasicInfo retrieves times and attributes for a file.
31func GetFileBasicInfo(f *os.File) (*FileBasicInfo, error) {
32 bi := &alignedFileBasicInfo{}
33 if err := windows.GetFileInformationByHandleEx(
34 windows.Handle(f.Fd()),
35 windows.FileBasicInfo,
36 (*byte)(unsafe.Pointer(bi)),
37 uint32(unsafe.Sizeof(*bi)),
38 ); err != nil {
39 return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
40 }
41 runtime.KeepAlive(f)
42 // Reinterpret the alignedFileBasicInfo as a FileBasicInfo so it matches the
43 // public API of this module. The data may be unnecessarily aligned.
44 return (*FileBasicInfo)(unsafe.Pointer(bi)), nil
45}
46
47// SetFileBasicInfo sets times and attributes for a file.
48func SetFileBasicInfo(f *os.File, bi *FileBasicInfo) error {
49 // Create an alignedFileBasicInfo based on a FileBasicInfo. The copy is
50 // suitable to pass to GetFileInformationByHandleEx.
51 biAligned := *(*alignedFileBasicInfo)(unsafe.Pointer(bi))
52 if err := windows.SetFileInformationByHandle(
53 windows.Handle(f.Fd()),
54 windows.FileBasicInfo,
55 (*byte)(unsafe.Pointer(&biAligned)),
56 uint32(unsafe.Sizeof(biAligned)),
57 ); err != nil {
58 return &os.PathError{Op: "SetFileInformationByHandle", Path: f.Name(), Err: err}
59 }
60 runtime.KeepAlive(f)
61 return nil
62}
63
64// FileStandardInfo contains extended information for the file.
65// FILE_STANDARD_INFO in WinBase.h
66// https://docs.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_standard_info
67type FileStandardInfo struct {
68 AllocationSize, EndOfFile int64
69 NumberOfLinks uint32
70 DeletePending, Directory bool
71}
72
73// GetFileStandardInfo retrieves ended information for the file.
74func GetFileStandardInfo(f *os.File) (*FileStandardInfo, error) {
75 si := &FileStandardInfo{}
76 if err := windows.GetFileInformationByHandleEx(windows.Handle(f.Fd()),
77 windows.FileStandardInfo,
78 (*byte)(unsafe.Pointer(si)),
79 uint32(unsafe.Sizeof(*si))); err != nil {
80 return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
81 }
82 runtime.KeepAlive(f)
83 return si, nil
84}
85
86// FileIDInfo contains the volume serial number and file ID for a file. This pair should be
87// unique on a system.
88type FileIDInfo struct {
89 VolumeSerialNumber uint64
90 FileID [16]byte
91}
92
93// GetFileID retrieves the unique (volume, file ID) pair for a file.
94func GetFileID(f *os.File) (*FileIDInfo, error) {
95 fileID := &FileIDInfo{}
96 if err := windows.GetFileInformationByHandleEx(
97 windows.Handle(f.Fd()),
98 windows.FileIdInfo,
99 (*byte)(unsafe.Pointer(fileID)),
100 uint32(unsafe.Sizeof(*fileID)),
101 ); err != nil {
102 return nil, &os.PathError{Op: "GetFileInformationByHandleEx", Path: f.Name(), Err: err}
103 }
104 runtime.KeepAlive(f)
105 return fileID, nil
106}