fileinfo.go 3.5 KB

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