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