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