The Pedigree Project 0.1
flock.c
1#define _GNU_SOURCE
2#include <unistd.h>
3
4#include "contract.h"
5#include <sys/file.h>
6
7int file_lock_flock(void) {
8 int failed = 0, a = -1, b = -1, readonly = -1;
9 char path[128] = {0}, byte = 'a';
10 CHECK((a = fl_file(path, "/tmp")) >= 0);
11 CHECK((b = open(path, O_RDWR)) >= 0 && (readonly = open(path, O_RDONLY)) >= 0);
12 CHECK(flock(-1, LOCK_EX) == -1 && errno == EBADF);
13 CHECK(flock(a, 0) == -1 && errno == EINVAL);
14 CHECK(flock(a, LOCK_SH | LOCK_EX) == -1 && errno == EINVAL);
15 CHECK(flock(a, LOCK_EX | 0x1000) == -1 && errno == EINVAL);
16 CHECK(flock(a, LOCK_EX | LOCK_NB) == 0);
17 CHECK(flock(b, LOCK_EX | LOCK_NB) == -1 && errno == EAGAIN);
18 CHECK(pwrite(b, &byte, 1, 0) == 1 && pread(a, &byte, 1, 0) == 1 && byte == 'a');
19 CHECK(fl_lock(b, FL_OFD, F_WRLCK, 0) == 0);
20 CHECK(fl_lock(b, FL_OFD, F_UNLCK, 0) == 0);
21 CHECK(flock(a, LOCK_SH) == 0 && flock(b, LOCK_SH) == 0);
22 CHECK(flock(a, LOCK_EX | LOCK_NB) == -1 && errno == EAGAIN);
23 // A failed flock upgrade has released a's old shared grant.
24 CHECK(flock(b, LOCK_EX | LOCK_NB) == 0);
25 CHECK(flock(a, LOCK_SH | LOCK_NB) == -1 && errno == EAGAIN);
26 CHECK(flock(b, LOCK_UN) == 0 && flock(b, LOCK_UN) == 0);
27 CHECK(flock(readonly, LOCK_EX | LOCK_NB) == 0);
28 CHECK(flock(a, LOCK_SH | LOCK_NB) == -1 && errno == EAGAIN);
29 CHECK(flock(readonly, LOCK_UN) == 0);
30out:
31 if (readonly >= 0)
32 close(readonly);
33 if (b >= 0)
34 close(b);
35 if (a >= 0)
36 close(a);
37 if (*path)
38 unlink(path);
39 return failed;
40}