forked from gravwell/buffer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathflock.go
71 lines (63 loc) · 1.46 KB
/
flock.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// +build !windows,!plan9,!solaris
//this package is based on the flock implementation used in boltdb
//which is MIT licensed and available at:
// https://github.com/boltdb/bolt/blob/master/bolt_unix.go
package buffer
import (
"errors"
"os"
"syscall"
)
var (
ErrTimeout = errors.New("Timeout")
ErrLocked = errors.New("File is already locked")
)
//flock locks a file for this process, this DOES NOT prevent the same process
//from opening the
func flock(f *os.File, exclusive bool) error {
var lock syscall.Flock_t
lock.Start = 0
lock.Len = 0
lock.Pid = 0
lock.Whence = 0
lock.Pid = 0
if exclusive {
lock.Type = syscall.F_WRLCK
} else {
lock.Type = syscall.F_RDLCK
}
err := rawFdCall(f, func(fd uintptr) error {
return syscall.FcntlFlock(fd, syscall.F_SETLK, &lock)
})
if err == nil {
return nil
} else if err == syscall.EAGAIN {
return ErrLocked
}
return err
}
//funlock releases a lock held on a file descriptor
func funlock(f *os.File) error {
var lock syscall.Flock_t
lock.Start = 0
lock.Len = 0
lock.Type = syscall.F_UNLCK
lock.Whence = 0
return rawFdCall(f, func(fd uintptr) error {
return syscall.FcntlFlock(fd, syscall.F_SETLK, &lock)
})
}
type controlFunc func(fd uintptr) error
func rawFdCall(fio *os.File, cf controlFunc) error {
if fio == nil || cf == nil {
return errors.New("invalid parameters")
}
rc, err := fio.SyscallConn()
if err != nil {
return err
}
rc.Control(func(fd uintptr) {
err = cf(fd)
})
return err
}