xref: /haiku/src/tests/system/libroot/posix/flock_test.cpp (revision 1deede7388b04dbeec5af85cae7164735ea9e70d)
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 
17 bool gDone = false;
18 
19 
20 static int32
21 try_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 
61 int
62 main(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