// +build windows package staros import ( "b612.me/win32api" "os" "syscall" "time" ) type FileLock struct { filepath string handle win32api.HANDLE } func GetFileCreationTime(fileinfo os.FileInfo) time.Time { d := fileinfo.Sys().(*syscall.Win32FileAttributeData) return time.Unix(0, d.CreationTime.Nanoseconds()) } func GetFileAccessTime(fileinfo os.FileInfo) time.Time { d := fileinfo.Sys().(*syscall.Win32FileAttributeData) return time.Unix(0, d.LastAccessTime.Nanoseconds()) } func SetFileTimes(file *os.File, info os.FileInfo) { } func SetFileTimesbyTime(file *os.File) { } func (f *FileLock) openFileForLock() error { name, err := syscall.UTF16PtrFromString(f.filepath) if err != nil { return err } handle, err := syscall.CreateFile( name, syscall.GENERIC_READ, syscall.FILE_SHARE_READ, nil, syscall.OPEN_ALWAYS, syscall.FILE_FLAG_OVERLAPPED|0x00000080, 0) if err != nil { return err } f.handle = win32api.HANDLE(handle) return nil } func (f *FileLock) lockForTimeout(timeout time.Duration, lockType win32api.DWORD) error { var err error if err = f.openFileForLock(); err != nil { return err } event, err := win32api.CreateEventW(nil, true, false, nil) if err != nil { return err } myEvent := &syscall.Overlapped{HEvent: syscall.Handle(event)} defer syscall.CloseHandle(myEvent.HEvent) _, err = win32api.LockFileEx(f.handle, lockType, 0, 1, 0, myEvent) if err == nil { return nil } if err != syscall.ERROR_IO_PENDING { return err } millis := uint32(syscall.INFINITE) if timeout >= 0 { millis = uint32(timeout.Nanoseconds() / 1000000) } s, err := syscall.WaitForSingleObject(myEvent.HEvent, millis) switch s { case syscall.WAIT_OBJECT_0: // success! return nil case syscall.WAIT_TIMEOUT: f.Unlock() return ERR_TIMEOUT default: f.Unlock() return err } } func (f *FileLock) Lock(Exclusive bool) error { var lockType win32api.DWORD if Exclusive { lockType = win32api.LOCKFILE_EXCLUSIVE_LOCK } else { lockType = 0 } return f.lockForTimeout(0, lockType) } func (f *FileLock) LockWithTimeout(tm time.Duration, Exclusive bool) error { var lockType win32api.DWORD if Exclusive { lockType = win32api.LOCKFILE_EXCLUSIVE_LOCK } else { lockType = 0 } return f.lockForTimeout(tm, lockType) } func (f *FileLock) LockNoBlocking(Exclusive bool) error { var lockType win32api.DWORD if Exclusive { lockType = win32api.LOCKFILE_EXCLUSIVE_LOCK } else { lockType = 0 } return f.lockForTimeout(0, lockType|win32api.LOCKFILE_FAIL_IMMEDIATELY) } func (f *FileLock) Unlock() error { return syscall.Close(syscall.Handle(f.handle)) }