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