1/*
2 * Copyright 2005, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <OS.h>
8
9#include <fcntl.h>
10#include <unistd.h>
11#include <stdio.h>
12#include <string.h>
13#include <errno.h>
14
15
16bool gDone = false;
17
18
19static int32
20try_to_lock(void *_fd)
21{
22	int fd = (int)_fd;
23
24	struct flock flock = {
25		F_RDLCK,	// shared lock
26		SEEK_SET,
27		200,
28		0,			// until the end of the file
29		0
30	};
31
32	if (fcntl(fd, F_SETLK, &flock) == 0) {
33		fprintf(stderr, "a. Could lock file!\n");
34		return -1;
35	} else
36		puts("test a passed.");
37
38	gDone = true;
39
40	// wait for lock to become free
41
42	if (fcntl(fd, F_SETLKW, &flock) == -1) {
43		fprintf(stderr, "b. Could not lock file: %s\n", strerror(errno));
44		return -1;
45	} else
46		puts("test b passed.");
47
48	flock.l_type = F_UNLCK;
49
50	if (fcntl(fd, F_SETLK, &flock) == -1) {
51		fprintf(stderr, "c. Could not unlock file: %s\n", strerror(errno));
52		return -1;
53	} else
54		puts("test c passed.");
55
56	return 0;
57}
58
59
60int
61main(int argc, char **argv)
62{
63	int fd = open("/bin/sh", O_RDONLY);
64	if (fd < 0) {
65		fprintf(stderr, "could not open file: %s\n", strerror(errno));
66		return -1;
67	}
68
69	struct flock flock = {
70		F_WRLCK,	// exclusive lock
71		SEEK_SET,	// lock whole file
72		0,
73		0,
74		0
75	};
76
77	if (fcntl(fd, F_SETLK, &flock) == 0) {
78		fprintf(stderr, "0. Could lock file exclusively without write access!\n");
79		return -1;
80	} else
81		puts("test 0 passed.");
82
83	flock.l_type = F_RDLCK;
84		// shared locks should be allowed
85
86	if (fcntl(fd, F_SETLK, &flock) == -1) {
87		fprintf(stderr, "1. Could not lock file: %s\n", strerror(errno));
88		return -1;
89	} else
90		puts("test 1 passed.");
91
92	close(fd);
93
94	fd = open("/bin/sh", O_RDWR);
95	if (fd < 0) {
96		fprintf(stderr, "could not open file: %s\n", strerror(errno));
97		return -1;
98	}
99
100	flock.l_type = F_WRLCK;
101	flock.l_start = 100;
102	flock.l_len = 42;
103
104	if (fcntl(fd, F_SETLK, &flock) == -1) {
105		fprintf(stderr, "2. Could not lock file: %s\n", strerror(errno));
106		return -1;
107	} else
108		puts("test 2 passed.");
109
110	flock.l_start = 200;
111
112	if (fcntl(fd, F_SETLK, &flock) == -1) {
113		fprintf(stderr, "3. Could not lock file: %s\n", strerror(errno));
114		return -1;
115	} else
116		puts("test 3 passed.");
117
118	flock.l_start = 80;
119
120	if (fcntl(fd, F_SETLK, &flock) == 0) {
121		fprintf(stderr, "4. Could lock file exclusively on locked region!\n");
122		return -1;
123	} else
124		puts("test 4 passed.");
125
126	flock.l_type = F_UNLCK;
127	flock.l_start = 100;
128
129	if (fcntl(fd, F_SETLK, &flock) == -1) {
130		fprintf(stderr, "5. Could not unlock file: %s\n", strerror(errno));
131		return -1;
132	} else
133		puts("test 5 passed.");
134
135	flock.l_type = F_WRLCK;
136	flock.l_start = 80;
137
138	if (fcntl(fd, F_SETLK, &flock) == -1) {
139		fprintf(stderr, "6. Could not lock file: %s\n", strerror(errno));
140		return -1;
141	} else
142		puts("test 6 passed.");
143
144	thread_id thread = spawn_thread(try_to_lock, "try", B_NORMAL_PRIORITY, (void *)fd);
145	if (thread < B_OK) {
146		fprintf(stderr, "Could not spawn thread: %s\n", strerror(thread));
147		return -1;
148	}
149	resume_thread(thread);
150
151	while (!gDone) {
152		snooze(100000); // 0.1s
153	}
154
155	flock.l_type = F_UNLCK;
156	flock.l_start = 200;
157
158	if (fcntl(fd, F_SETLK, &flock) == -1) {
159		fprintf(stderr, "7. Could not unlock file: %s\n", strerror(errno));
160		return -1;
161	} else
162		puts("test 7 passed.");
163
164	status_t returnCode;
165	wait_for_thread(thread, &returnCode);
166
167	close(fd);
168	return 0;
169}
170