v2 / vlib / os / filelock / lib_nix.c.v
92 lines · 83 sloc · 1.99 KB · e2e5cf8db56f3562c7baa735061690be936bdf3e
Raw
1module filelock
2
3#include <sys/file.h>
4#insert "@VEXEROOT/vlib/os/filelock/filelock_helpers.h"
5
6fn C.unlink(&char) i32
7fn C.open(&char, i32, i32) i32
8fn C.close(i32) i32
9fn C.flock(i32, i32) i32
10fn C.v_filelock_lock(i32, i32, i32, u64, u64) i32
11fn C.v_filelock_unlock(i32, u64, u64) i32
12
13fn (l &FileLock) open_lock() int {
14 if l.target == .file {
15 return open_existing_file(l.name, l.mode)
16 }
17 return open_lockfile(l.name)
18}
19
20fn open_lockfile(path string) int {
21 mut fd := C.open(&char(path.str), C.O_CREAT | C.O_RDONLY, 0o644)
22 if fd == -1 {
23 fd = C.open(&char(path.str), C.O_RDONLY, 0)
24 }
25 return fd
26}
27
28fn open_existing_file(path string, mode LockMode) int {
29 flags := if mode == .shared { C.O_RDONLY } else { C.O_RDWR }
30 return C.open(&char(path.str), flags, 0)
31}
32
33fn (l &FileLock) lock_fd(fd int, immediate bool) bool {
34 if l.target == .file {
35 return C.v_filelock_lock(fd, int(l.mode == .exclusive), int(immediate), l.start, l.len) == 0
36 }
37 flags := if immediate { C.LOCK_EX | C.LOCK_NB } else { C.LOCK_EX }
38 return C.flock(fd, flags) == 0
39}
40
41fn (mut l FileLock) close_lock() {
42 if l.fd == -1 {
43 return
44 }
45 fd := int(l.fd)
46 if l.target == .file {
47 C.v_filelock_unlock(fd, l.start, l.len)
48 C.close(fd)
49 } else {
50 C.close(fd)
51 C.unlink(&char(l.name.str))
52 }
53 l.fd = -1
54}
55
56// acquire blocks until the lock is acquired.
57pub fn (mut l FileLock) acquire() ! {
58 if l.fd != -1 {
59 return error_with_code('lock already acquired by this instance', 1)
60 }
61 fd := l.open_lock()
62 if fd == -1 {
63 msg := if l.target == .file {
64 'cannot open file ${l.name}'
65 } else {
66 'cannot create lock file ${l.name}'
67 }
68 return error_with_code(msg, -1)
69 }
70 if !l.lock_fd(fd, false) {
71 C.close(fd)
72 return error_with_code('cannot lock ${l.name}', -2)
73 }
74 l.fd = fd
75}
76
77// try_acquire tries to acquire the lock without blocking.
78pub fn (mut l FileLock) try_acquire() bool {
79 if l.fd != -1 {
80 return true
81 }
82 fd := l.open_lock()
83 if fd == -1 {
84 return false
85 }
86 if !l.lock_fd(fd, true) {
87 C.close(fd)
88 return false
89 }
90 l.fd = fd
91 return true
92}
93