1// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5//go:build windows
6
7package filelock
8
9import (
10	"internal/syscall/windows"
11	"io/fs"
12	"syscall"
13)
14
15type lockType uint32
16
17const (
18	readLock  lockType = 0
19	writeLock lockType = windows.LOCKFILE_EXCLUSIVE_LOCK
20)
21
22const (
23	reserved = 0
24	allBytes = ^uint32(0)
25)
26
27func lock(f File, lt lockType) error {
28	// Per https://golang.org/issue/19098, “Programs currently expect the Fd
29	// method to return a handle that uses ordinary synchronous I/O.”
30	// However, LockFileEx still requires an OVERLAPPED structure,
31	// which contains the file offset of the beginning of the lock range.
32	// We want to lock the entire file, so we leave the offset as zero.
33	ol := new(syscall.Overlapped)
34
35	err := windows.LockFileEx(syscall.Handle(f.Fd()), uint32(lt), reserved, allBytes, allBytes, ol)
36	if err != nil {
37		return &fs.PathError{
38			Op:   lt.String(),
39			Path: f.Name(),
40			Err:  err,
41		}
42	}
43	return nil
44}
45
46func unlock(f File) error {
47	ol := new(syscall.Overlapped)
48	err := windows.UnlockFileEx(syscall.Handle(f.Fd()), reserved, allBytes, allBytes, ol)
49	if err != nil {
50		return &fs.PathError{
51			Op:   "Unlock",
52			Path: f.Name(),
53			Err:  err,
54		}
55	}
56	return nil
57}
58