...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package fileutil
19
20 import (
21 "fmt"
22 "io"
23 "os"
24 "syscall"
25
26 "golang.org/x/sys/unix"
27 )
28
29
30
31
32
33
34 var (
35 wrlck = syscall.Flock_t{
36 Type: syscall.F_WRLCK,
37 Whence: int16(io.SeekStart),
38 Start: 0,
39 Len: 0,
40 }
41
42 linuxTryLockFile = flockTryLockFile
43 linuxLockFile = flockLockFile
44 )
45
46 func init() {
47
48 getlk := syscall.Flock_t{Type: syscall.F_RDLCK}
49 if err := syscall.FcntlFlock(0, unix.F_OFD_GETLK, &getlk); err == nil {
50 linuxTryLockFile = ofdTryLockFile
51 linuxLockFile = ofdLockFile
52 }
53 }
54
55 func TryLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
56 return linuxTryLockFile(path, flag, perm)
57 }
58
59 func ofdTryLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
60 f, err := os.OpenFile(path, flag, perm)
61 if err != nil {
62 return nil, fmt.Errorf("ofdTryLockFile failed to open %q (%v)", path, err)
63 }
64
65 flock := wrlck
66 if err = syscall.FcntlFlock(f.Fd(), unix.F_OFD_SETLK, &flock); err != nil {
67 f.Close()
68 if err == syscall.EWOULDBLOCK {
69 err = ErrLocked
70 }
71 return nil, err
72 }
73 return &LockedFile{f}, nil
74 }
75
76 func LockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
77 return linuxLockFile(path, flag, perm)
78 }
79
80 func ofdLockFile(path string, flag int, perm os.FileMode) (*LockedFile, error) {
81 f, err := os.OpenFile(path, flag, perm)
82 if err != nil {
83 return nil, fmt.Errorf("ofdLockFile failed to open %q (%v)", path, err)
84 }
85
86 flock := wrlck
87 err = syscall.FcntlFlock(f.Fd(), unix.F_OFD_SETLKW, &flock)
88 if err != nil {
89 f.Close()
90 return nil, err
91 }
92 return &LockedFile{f}, nil
93 }
94
View as plain text