9static int ranges(
void) {
10 int failed = 0, a = -1, b = -1;
12 CHECK((a = fl_file(path,
"/tmp")) >= 0 && (b = open(path, O_RDWR)) >= 0);
13 CHECK(fl_record(a, F_OFD_SETLK, F_WRLCK, SEEK_SET, 100, 20) == 0);
14 CHECK(fl_query(b, F_GETLK, 110, 1, F_WRLCK, 100, 20, -1) == 0);
15 CHECK(fl_query(a, F_OFD_GETLK, 110, 1, F_UNLCK, 0, 0, 0) == 0);
16 struct flock own = {.l_type = F_UNLCK, .l_whence = SEEK_SET, .l_start = 110, .l_len = 1};
17 CHECK(fcntl(a, F_OFD_GETLK, &own) == 0 && own.l_type == F_WRLCK && own.l_whence == SEEK_SET &&
18 own.l_start == 100 && own.l_len == 20 && own.l_pid == -1);
19 own = (
struct flock){.l_type = F_UNLCK, .l_whence = SEEK_SET, .l_start = 110, .l_len = 1};
20 CHECK(fcntl(b, F_OFD_GETLK, &own) == 0 && own.l_type == F_UNLCK);
21 CHECK(fl_record(b, F_SETLK, F_WRLCK, SEEK_SET, 110, 1) == -1 && errno == EAGAIN);
22 CHECK(fl_lock(a, FL_OFD, F_UNLCK, 0) == 0);
23 CHECK(fl_record(a, F_SETLK, F_WRLCK, SEEK_SET, 20, 10) == 0);
24 CHECK(fl_query(b, F_OFD_GETLK, 20, 1, F_WRLCK, 20, 10, getpid()) == 0);
25 CHECK(fl_query(b, F_GETLK, 20, 1, F_UNLCK, 0, 0, 0) == 0);
26 CHECK(fl_lock(a, FL_CLASSIC, F_UNLCK, 0) == 0);
28 CHECK(lseek(a, 40, SEEK_SET) == 40);
29 CHECK(fl_record(a, F_OFD_SETLK, F_WRLCK, SEEK_CUR, -10, -10) == 0);
30 CHECK(fl_query(b, F_OFD_GETLK, 20, 1, F_WRLCK, 20, 10, -1) == 0);
31 CHECK(lseek(a, 0, SEEK_CUR) == 40);
32 CHECK(fl_lock(a, FL_OFD, F_UNLCK, 0) == 0);
33 CHECK(fl_record(a, F_OFD_SETLK, F_WRLCK, SEEK_END, -8, 0) == 0);
34 CHECK(ftruncate(a, 256) == 0);
35 CHECK(fl_query(b, F_GETLK, 1000, 1, F_WRLCK, 120, 0, -1) == 0);
36 CHECK(fl_lock(a, FL_OFD, F_UNLCK, 0) == 0);
38 CHECK(fl_record(a, F_OFD_SETLK, F_WRLCK, SEEK_SET, 0, 100) == 0);
39 CHECK(fl_record(a, F_OFD_SETLK, F_RDLCK, SEEK_SET, 20, 20) == 0);
40 CHECK(fl_record(b, F_OFD_SETLK, F_RDLCK, SEEK_SET, 20, 20) == 0);
41 CHECK(fl_record(a, F_OFD_SETLK, F_WRLCK, SEEK_SET, 20, 20) == -1 && errno == EAGAIN);
42 CHECK(fl_lock(b, FL_OFD, F_UNLCK, 0) == 0);
43 CHECK(fl_query(b, F_GETLK, 0, 1, F_WRLCK, 0, 20, -1) == 0);
44 CHECK(fl_query(b, F_GETLK, 20, 1, F_RDLCK, 20, 20, -1) == 0);
45 CHECK(fl_query(b, F_GETLK, 40, 1, F_WRLCK, 40, 60, -1) == 0);
46 CHECK(fl_record(a, F_OFD_SETLK, F_UNLCK, SEEK_SET, 25, 10) == 0);
47 CHECK(fl_record(b, F_OFD_SETLK, F_WRLCK, SEEK_SET, 25, 10) == 0);
48 CHECK(fl_record(a, F_OFD_SETLK, F_WRLCK, SEEK_SET, 20, 20) == -1 && errno == EAGAIN);
49 CHECK(fl_query(b, F_GETLK, 20, 1, F_RDLCK, 20, 5, -1) == 0);
50 CHECK(fl_query(b, F_GETLK, 35, 1, F_RDLCK, 35, 5, -1) == 0);
51 CHECK(fl_lock(b, FL_OFD, F_UNLCK, 0) == 0);
52 CHECK(fl_record(a, F_OFD_SETLK, F_WRLCK, SEEK_SET, 20, 20) == 0);
53 CHECK(fl_query(b, F_GETLK, 80, 1, F_WRLCK, 0, 100, -1) == 0);
64static int errors(
void) {
65 int failed = 0, a = -1, b = -1, ro = -1, wo = -1;
67 const size_t page = (size_t)sysconf(_SC_PAGESIZE);
68 struct flock* wire = mmap(NULL, page, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
69 CHECK(wire != MAP_FAILED);
70 CHECK((a = fl_file(path,
"/tmp")) >= 0 && (b = open(path, O_RDWR)) >= 0);
71 CHECK((ro = open(path, O_RDONLY)) >= 0 && (wo = open(path, O_WRONLY)) >= 0);
72 CHECK(fl_record(-1, F_SETLK, F_WRLCK, SEEK_SET, 0, 1) == -1 && errno == EBADF);
73 CHECK(fl_record(a, F_SETLK, 99, SEEK_SET, 0, 1) == -1 && errno == EINVAL);
74 CHECK(fl_record(a, F_SETLK, F_WRLCK, 99, 0, 1) == -1 && errno == EINVAL);
75 CHECK(fl_record(a, F_SETLK, F_WRLCK, SEEK_SET, -1, 1) == -1 && errno == EINVAL);
76 CHECK(fl_record(a, F_SETLK, F_WRLCK, SEEK_SET, 0, -1) == -1 && errno == EINVAL);
77 CHECK(fl_record(a, F_SETLK, F_WRLCK, SEEK_SET, INT64_MAX, 2) == -1 && errno == EOVERFLOW);
78 CHECK(lseek(a, 1, SEEK_SET) == 1);
79 CHECK(fl_record(a, F_SETLK, F_WRLCK, SEEK_CUR, INT64_MAX, 1) == -1 && errno == EOVERFLOW);
80 for (
int n = 0; n < 2; ++n) {
81 const int command = n ? F_OFD_SETLK : F_SETLK;
82 CHECK(fl_record(ro, command, F_WRLCK, SEEK_SET, 0, 1) == -1 && errno == EBADF);
83 CHECK(fl_record(wo, command, F_RDLCK, SEEK_SET, 0, 1) == -1 && errno == EBADF);
85 CHECK(fl_query(ro, F_OFD_GETLK, 0, 1, F_UNLCK, 0, 0, 0) == 0);
86 *wire = (
struct flock){.l_type = F_WRLCK, .l_whence = SEEK_SET, .l_len = 1, .l_pid = 9};
87 CHECK(fcntl(a, F_OFD_SETLK, wire) == -1 && errno == EINVAL);
88 CHECK(fcntl(a, F_OFD_GETLK, wire) == -1 && errno == EINVAL);
89 CHECK(fcntl(a, F_OFD_SETLKW, wire) == -1 && errno == EINVAL);
91 memset(wire, 0xa5,
sizeof(*wire));
92 wire->l_type = F_WRLCK;
93 wire->l_whence = SEEK_SET;
97 struct flock expected;
98 memcpy(&expected, wire,
sizeof(expected));
99 expected.l_type = F_UNLCK;
100 CHECK(fcntl(a, F_OFD_GETLK, wire) == 0 && !memcmp(wire, &expected,
sizeof(expected)));
101 CHECK(fl_record(a, F_OFD_SETLK, F_WRLCK, SEEK_SET, 0, 10) == 0);
102 *wire = (
struct flock){.l_type = F_WRLCK, .l_whence = SEEK_SET, .l_len = 1};
103 CHECK(mprotect(wire, page, PROT_READ) == 0);
104 CHECK(fcntl(b, F_OFD_GETLK, wire) == -1 && errno == EFAULT);
105 CHECK(fl_query(b, F_OFD_GETLK, 0, 1, F_WRLCK, 0, 10, -1) == 0);
106 CHECK(mprotect(wire, page, PROT_NONE) == 0);
107 CHECK(fcntl(b, F_SETLK, wire) == -1 && errno == EFAULT);
108 CHECK(fcntl(b, F_GETLK, wire) == -1 && errno == EFAULT);
110 if (wire != MAP_FAILED)
124int file_lock_records(
void) {
125 return ranges() || errors();