Print this page
10703 smatch unreachable code checking needs reworking
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/test/os-tests/tests/file-locking/runtests.c
+++ new/usr/src/test/os-tests/tests/file-locking/runtests.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 - * Copyright 2018 Joyent, Inc.
13 + * Copyright 2019 Joyent, Inc.
14 14 */
15 15
16 16 /*
17 17 * Validate various fcntl(2) and flock(3C) operations.
18 18 */
19 19
20 20 #include "util.h"
21 21 #include <err.h>
22 22 #include <errno.h>
23 23 #include <fcntl.h>
24 24 #include <libgen.h>
25 25 #include <signal.h>
26 26 #include <stdlib.h>
27 27 #include <strings.h>
28 28 #include <sys/debug.h>
29 29 #include <sys/file.h>
30 30 #include <sys/stat.h>
31 31 #include <sys/wait.h>
32 32 #include <unistd.h>
33 33
34 34
35 35 #define LOCKFILE_FMT "/tmp/.lockfile-%s-%ld"
36 36 #define LOCKDIR_FMT "/tmp/.lockdir-%s-%ld"
37 37
38 38 typedef struct lockinfo {
39 39 char *lf_name;
40 40 char *lf_path;
41 41 int lf_fd;
42 42 } lockinfo_t;
43 43
44 44
45 45 static void assert_write_locked_by(lockinfo_t *, pid_t);
46 46 static void assert_read_locked_by(lockinfo_t *, pid_t);
47 47 static void assert_unlocked(lockinfo_t *);
48 48 static void assert_all_unlocked(void);
49 49
50 50 static int flock_copyfil(lockinfo_t *, lockinfo_t *);
51 51 static int flock_mkfil(lockinfo_t *);
52 52 static int flock_mkdir(lockinfo_t *);
53 53 static void flock_rminfo(lockinfo_t *);
54 54
55 55 static void flock_fcntl(lockinfo_t *lf, int cmd, struct flock *fl);
56 56 static void flock_run(lock_style_t, boolean_t, lockinfo_t *,
57 57 pid_t *, int[]);
58 58 static int flock_wait(pid_t pid);
59 59 static void flock_cleanup_child(pid_t, int []);
60 60
61 61 static void flock_test_invalid(lockinfo_t *, int, short, short,
62 62 off_t, off_t);
63 63 static void flock_test_invalid64(lockinfo_t *, int, short, short,
64 64 off_t, off_t);
65 65 static void flock_test_exclusive(lock_style_t, lock_style_t,
66 66 lockinfo_t *, lockinfo_t *, boolean_t);
67 67 static void flock_test_shared(lock_style_t, lock_style_t, lockinfo_t *,
68 68 lockinfo_t *, boolean_t);
69 69 static void flock_test_upgrade_downgrade(void);
70 70
71 71 static char *acqprog = NULL;
72 72
73 73 static lockinfo_t flock_fileA = { "a", NULL, -1 };
74 74 static lockinfo_t flock_fileB = { "b", NULL, -1 };
75 75 static lockinfo_t flock_dirA = { "a", NULL, -1 };
76 76 static lockinfo_t flock_dirB = { "b", NULL, -1 };
77 77
78 78
79 79 static short cmds[8] = {
80 80 F_SETLK, F_SETLKW, F_GETLK,
81 81 F_OFD_SETLK, F_OFD_SETLKW, F_OFD_GETLK,
82 82 F_FLOCK, F_FLOCKW
83 83 };
84 84
85 85 static short cmds64[3] = {
86 86 F_OFD_SETLK64, F_OFD_SETLKW64, F_OFD_GETLK64
87 87 };
88 88
89 89
90 90 static void
91 91 flock_kill(pid_t pid)
92 92 {
93 93 while (kill(pid, SIGKILL) == -1) {
94 94 if (errno == EINTR)
95 95 continue;
96 96
97 97 err(EXIT_FAILURE, "kill failed");
98 98 }
99 99 }
100 100
101 101
102 102 static void
103 103 flock_fcntl(lockinfo_t *lf, int cmd, struct flock *fl)
104 104 {
105 105 if (fcntl(lf->lf_fd, cmd, fl) == -1) {
106 106 err(EXIT_FAILURE, "fcntl failed");
107 107 }
108 108 }
109 109
110 110
111 111 static void
112 112 assert_write_locked_by(lockinfo_t *lf, pid_t pid)
113 113 {
114 114 struct flock fl;
115 115
116 116 flock_reinit(&fl, F_WRLCK);
117 117 flock_fcntl(lf, F_GETLK, &fl);
118 118 VERIFY3_IMPL(fl.l_type, ==, F_WRLCK, short);
119 119 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
120 120 VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
121 121
122 122 flock_reinit(&fl, F_WRLCK);
123 123 flock_fcntl(lf, F_OFD_GETLK, &fl);
124 124 VERIFY3_IMPL(fl.l_type, ==, F_WRLCK, short);
125 125 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
126 126 VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
127 127
128 128 flock_reinit(&fl, F_RDLCK);
129 129 flock_fcntl(lf, F_GETLK, &fl);
130 130 VERIFY3_IMPL(fl.l_type, ==, F_WRLCK, short);
131 131 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
132 132 VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
133 133
134 134 flock_reinit(&fl, F_RDLCK);
135 135 flock_fcntl(lf, F_OFD_GETLK, &fl);
136 136 VERIFY3_IMPL(fl.l_type, ==, F_WRLCK, short);
137 137 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
138 138 VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
139 139 }
140 140
141 141
142 142 static void
143 143 assert_read_locked_by(lockinfo_t *lf, pid_t pid)
144 144 {
145 145 struct flock fl;
146 146
147 147 flock_reinit(&fl, F_WRLCK);
148 148 flock_fcntl(lf, F_GETLK, &fl);
149 149 VERIFY3_IMPL(fl.l_type, ==, F_RDLCK, short);
150 150 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
151 151 VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
152 152
153 153 flock_reinit(&fl, F_WRLCK);
154 154 flock_fcntl(lf, F_OFD_GETLK, &fl);
155 155 VERIFY3_IMPL(fl.l_type, ==, F_RDLCK, short);
156 156 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
157 157 VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
158 158
159 159 flock_reinit(&fl, F_RDLCK);
160 160 flock_fcntl(lf, F_GETLK, &fl);
161 161 VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
162 162 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
163 163 VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
164 164
165 165 flock_reinit(&fl, F_RDLCK);
166 166 flock_fcntl(lf, F_OFD_GETLK, &fl);
167 167 VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
168 168 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
169 169 VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
170 170 }
171 171
172 172 static void
173 173 assert_unlocked(lockinfo_t *lf)
174 174 {
175 175 struct flock fl;
176 176
177 177 flock_reinit(&fl, F_WRLCK);
178 178 flock_fcntl(lf, F_GETLK, &fl);
179 179 VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
180 180 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
181 181 VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
182 182
183 183 flock_reinit(&fl, F_WRLCK);
184 184 flock_fcntl(lf, F_OFD_GETLK, &fl);
185 185 VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
186 186 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
187 187 VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
188 188
189 189 flock_reinit(&fl, F_RDLCK);
190 190 flock_fcntl(lf, F_GETLK, &fl);
191 191 VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
192 192 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
193 193 VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
194 194
195 195 flock_reinit(&fl, F_RDLCK);
196 196 flock_fcntl(lf, F_OFD_GETLK, &fl);
197 197 VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
198 198 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
199 199 VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
200 200 }
201 201
202 202
203 203 static void
204 204 assert_all_unlocked(void)
205 205 {
206 206 assert_unlocked(&flock_fileA);
207 207 assert_unlocked(&flock_fileB);
208 208 assert_unlocked(&flock_dirA);
209 209 assert_unlocked(&flock_dirB);
210 210 }
211 211
212 212
213 213 static int
214 214 flock_copyfil(lockinfo_t *src, lockinfo_t *dst)
215 215 {
216 216 dst->lf_name = NULL;
217 217 dst->lf_path = NULL;
218 218 if ((dst->lf_fd = open(src->lf_path, O_RDWR)) == -1) {
219 219 warn("Failed to open %s", src->lf_path);
220 220 return (-1);
221 221 }
222 222
223 223 return (0);
224 224 }
225 225
226 226
227 227 static int
228 228 flock_mkfil(lockinfo_t *lf)
229 229 {
230 230 if (asprintf(&lf->lf_path, LOCKFILE_FMT, lf->lf_name, getpid()) < 0) {
231 231 warnx("Failed to generate lockfile name");
232 232 return (-1);
233 233 }
234 234
235 235 if ((lf->lf_fd = open(lf->lf_path, O_RDWR|O_CREAT, 0600)) == -1) {
236 236 warn("Failed to open %s", lf->lf_path);
237 237 return (-1);
238 238 }
239 239
240 240 return (0);
241 241 }
242 242
243 243
244 244 static int
245 245 flock_mkdir(lockinfo_t *lf)
246 246 {
247 247 if (asprintf(&lf->lf_path, LOCKDIR_FMT, lf->lf_name, getpid()) < 0) {
248 248 warnx("Failed to generate lockfile name");
249 249 return (-1);
250 250 }
251 251
252 252 if (mkdir(lf->lf_path, 0700) == -1) {
253 253 warn("Failed to make %s", lf->lf_path);
254 254 return (-1);
255 255 }
256 256
257 257 if ((lf->lf_fd = open(lf->lf_path, O_RDONLY)) == -1) {
258 258 warn("Failed to open %s", lf->lf_path);
259 259 return (-1);
260 260 }
261 261
262 262 return (0);
263 263 }
264 264
265 265
266 266 static void
267 267 flock_rminfo(lockinfo_t *lf)
268 268 {
269 269 if (lf->lf_fd != -1) {
270 270 (void) close(lf->lf_fd);
271 271 }
272 272 if (lf->lf_path != NULL) {
273 273 (void) unlink(lf->lf_path);
274 274 free(lf->lf_path);
275 275 }
276 276 }
277 277
278 278
279 279 static void
280 280 flock_run(lock_style_t style, boolean_t is_exclusive, lockinfo_t *lf,
281 281 pid_t *pid, int fds[])
282 282 {
283 283 char *stylestr = flock_stylestr(style);
284 284 char *modestr = is_exclusive ? "exclusive" : "shared";
285 285 char *argv[5] = { acqprog, stylestr, modestr, lf->lf_path, NULL };
286 286 int ret = pipe(fds);
287 287 if (ret == -1) {
288 288 err(EXIT_FAILURE, "pipe failed");
289 289 }
290 290
291 291 *pid = fork();
292 292 if (*pid == (pid_t)-1) {
293 293 err(EXIT_FAILURE, "fork failed");
294 294 } else if (*pid == (pid_t)0) {
295 295 /* Set up pipe for communicating with child */
296 296 ret = dup2(fds[1], 0);
297 297 if (ret == -1) {
298 298 err(EXIT_FAILURE, "dup2 failed");
299 299 }
300 300 ret = dup2(fds[1], 1);
301 301 if (ret == -1) {
302 302 err(EXIT_FAILURE, "dup2 failed");
303 303 }
304 304 closefrom(3);
305 305
306 306 (void) execv(acqprog, argv);
307 307 err(EXIT_FAILURE, "Failed to execute %s", acqprog);
308 308 }
309 309 }
310 310
311 311
312 312 static int
313 313 flock_wait(pid_t pid)
314 314 {
315 315 int childstat = 0;
316 316
317 317 while (waitpid(pid, &childstat, 0) == -1) {
318 318 if (errno == EINTR)
319 319 continue;
↓ open down ↓ |
296 lines elided |
↑ open up ↑ |
320 320
321 321 err(EXIT_FAILURE, "Failed to wait on child");
322 322 }
323 323
324 324 if (WIFEXITED(childstat)) {
325 325 return (WEXITSTATUS(childstat));
326 326 } else if (WIFSIGNALED(childstat)) {
327 327 return (1);
328 328 } else {
329 329 abort();
330 - return (1);
331 330 }
332 331 }
333 332
334 333
335 334 static void
336 335 flock_cleanup_child(pid_t pid, int fds[])
337 336 {
338 337 (void) flock_wait(pid);
339 338 (void) close(fds[0]);
340 339 (void) close(fds[1]);
341 340 }
342 341
343 342
344 343 static void
345 344 flock_test_upgrade_downgrade(void)
346 345 {
347 346 lockinfo_t afd1, afd2, afd3;
348 347 pid_t pid;
349 348 int fds[2];
350 349
351 350 VERIFY3S(flock_copyfil(&flock_fileA, &afd1), ==, 0);
352 351 VERIFY3S(flock_copyfil(&flock_fileA, &afd2), ==, 0);
353 352 VERIFY3S(flock_copyfil(&flock_fileA, &afd3), ==, 0);
354 353
355 354 flock_log("Acquiring shared locks 1, 2 and 3...");
356 355 VERIFY3S(flock(afd1.lf_fd, LOCK_SH), ==, 0);
357 356 VERIFY3S(flock(afd2.lf_fd, LOCK_SH), ==, 0);
358 357 VERIFY3S(flock(afd3.lf_fd, LOCK_SH), ==, 0);
359 358 assert_read_locked_by(&flock_fileA, -1);
360 359 flock_log(" ok\n");
361 360
362 361 flock_log("Upgrading lock 3 should fail w/ EWOULDBLOCK...");
363 362 VERIFY3S(flock(afd3.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
364 363 VERIFY3U(errno, ==, EWOULDBLOCK);
365 364 assert_read_locked_by(&flock_fileA, -1);
366 365 flock_log(" ok\n");
367 366
368 367 flock_log("Upgrading 3 should succeed after releasing locks 1 & 2...");
369 368 VERIFY3S(flock(afd1.lf_fd, LOCK_UN), ==, 0);
370 369 VERIFY3S(flock(afd2.lf_fd, LOCK_UN), ==, 0);
371 370 VERIFY3S(flock(afd3.lf_fd, LOCK_EX), ==, 0);
372 371 assert_write_locked_by(&flock_fileA, -1);
373 372 flock_log(" ok\n");
374 373
375 374
376 375 flock_log("Starting up child, then downgrading lock 3 to shared...");
377 376 flock_run(LSTYLE_FLOCK, B_FALSE, &flock_fileA, &pid, fds);
378 377 VERIFY3_IMPL(flock_nodata(fds[0]), ==, B_TRUE, boolean_t);
379 378 VERIFY3S(flock(afd3.lf_fd, LOCK_SH), ==, 0);
380 379 flock_block(fds[0]);
381 380 assert_read_locked_by(&flock_fileA, -1);
382 381 flock_log(" ok\n");
383 382
384 383 flock_log("Releasing child and upgrading...");
385 384 flock_alert(fds[0]);
386 385 flock_cleanup_child(pid, fds);
387 386 assert_read_locked_by(&flock_fileA, -1);
388 387 VERIFY3S(flock(afd3.lf_fd, LOCK_EX), ==, 0);
389 388 assert_write_locked_by(&flock_fileA, -1);
390 389 flock_log(" ok\n");
391 390
392 391 flock_log("Releasing lock 3...");
393 392 VERIFY3S(flock(afd3.lf_fd, LOCK_UN), ==, 0);
394 393 flock_rminfo(&afd1);
395 394 flock_rminfo(&afd2);
396 395 flock_rminfo(&afd3);
397 396 assert_all_unlocked();
398 397 flock_log(" ok\n");
399 398 }
400 399
401 400
402 401 static void
403 402 flock_test_invalid(lockinfo_t *lf, int cmd, short l_type, short l_whence,
404 403 off_t l_start, off_t l_len)
405 404 {
406 405 struct flock fl = {
407 406 .l_type = l_type,
408 407 .l_whence = l_whence,
409 408 .l_start = l_start,
410 409 .l_len = l_len
411 410 };
412 411
413 412 flock_log("fcntl(fd, %s, { %hd, %hd, %ld, %ld, ... })...",
414 413 flock_cmdname(cmd), l_type, l_whence, l_start, l_len);
415 414 VERIFY3S(fcntl(lf->lf_fd, cmd, &fl), ==, -1);
416 415 VERIFY3U(errno, ==, EINVAL);
417 416 flock_log(" ok\n");
418 417 }
419 418
420 419 static void
421 420 flock_test_invalid64(lockinfo_t *lf, int cmd, short l_type, short l_whence,
422 421 off_t l_start, off_t l_len)
423 422 {
424 423 struct flock64 fl = {
425 424 .l_type = l_type,
426 425 .l_whence = l_whence,
427 426 .l_start = l_start,
428 427 .l_len = l_len
429 428 };
430 429
431 430 flock_log("fcntl(fd, %s, { %hd, %hd, %ld, %ld, ... })...",
432 431 flock_cmdname(cmd), l_type, l_whence, l_start, l_len);
433 432 VERIFY3S(fcntl(lf->lf_fd, cmd, &fl), ==, -1);
434 433 VERIFY3U(errno, ==, EINVAL);
435 434 flock_log(" ok\n");
436 435 }
437 436
438 437 static void
439 438 flock_test_exclusive(lock_style_t styleA, lock_style_t styleB,
440 439 lockinfo_t *lock1, lockinfo_t *lock2, boolean_t kill_firstborn)
441 440 {
442 441 pid_t pidA, pidB;
443 442 int fdsA[2], fdsB[2];
444 443
445 444 flock_log("Running %s + %s tests (%s)...",
446 445 flock_stylename(styleA), flock_stylename(styleB),
447 446 kill_firstborn ? "kill child" : "child exits");
448 447
449 448 /* Create child, and wait for it to acquire the lock */
450 449 flock_run(styleA, B_TRUE, lock1, &pidA, fdsA);
451 450 flock_block(fdsA[0]);
452 451
453 452 /* Create second child, which shouldn't acquire & signal */
454 453 flock_run(styleB, B_TRUE, lock1, &pidB, fdsB);
455 454 VERIFY3_IMPL(flock_nodata(fdsB[0]), ==, B_TRUE, boolean_t);
456 455
457 456 /* lock1 is blocked for reading and writing */
458 457 assert_write_locked_by(lock1, styleA == LSTYLE_POSIX ? pidA : -1);
459 458 assert_unlocked(lock2);
460 459
461 460 /* Tell pidA to exit */
462 461 if (kill_firstborn) {
463 462 flock_kill(pidA);
464 463 } else {
465 464 flock_alert(fdsA[0]);
466 465 }
467 466 flock_cleanup_child(pidA, fdsA);
468 467
469 468 /* Wait for pidB to signal us */
470 469 flock_block(fdsB[0]);
471 470
472 471 /* lock1 is blocked for reading and writing */
473 472 assert_write_locked_by(lock1, styleB == LSTYLE_POSIX ? pidB : -1);
474 473 assert_unlocked(lock2);
475 474
476 475 /* Tell pidB to exit */
477 476 flock_alert(fdsB[0]);
478 477
479 478 flock_cleanup_child(pidB, fdsB);
480 479
481 480 /*
482 481 * Tests after child has released lock
483 482 */
484 483 assert_all_unlocked();
485 484
486 485 flock_log(" ok\n");
487 486 }
488 487
489 488
490 489 static void
491 490 flock_test_shared(lock_style_t styleA, lock_style_t styleB,
492 491 lockinfo_t *lock1, lockinfo_t *lock2, boolean_t kill_firstborn)
493 492 {
494 493 pid_t pidA, pidB;
495 494 int fdsA[2], fdsB[2];
496 495
497 496 flock_log("Running %s + %s tests (%s)...",
498 497 flock_stylename(styleA), flock_stylename(styleB),
499 498 kill_firstborn ? "kill child" : "child exits");
500 499
501 500 /* Create children, and wait for it to acquire the lock */
502 501 flock_run(styleB, B_FALSE, lock1, &pidB, fdsB);
503 502 flock_block(fdsB[0]);
504 503 flock_run(styleA, B_FALSE, lock1, &pidA, fdsA);
505 504 flock_block(fdsA[0]);
506 505
507 506 /* testfileA is only blocked for writing */
508 507 assert_read_locked_by(lock1, styleA == LSTYLE_POSIX ? pidA : -1);
509 508 assert_unlocked(lock2);
510 509
511 510 /* Tell pidA to exit */
512 511 if (kill_firstborn) {
513 512 flock_kill(pidA);
514 513 } else {
515 514 flock_alert(fdsA[0]);
516 515 }
517 516 flock_cleanup_child(pidA, fdsA);
518 517
519 518 /* testfileA is still blocked for writing by pidB */
520 519 assert_read_locked_by(lock1, styleB == LSTYLE_POSIX ? pidB : -1);
521 520 assert_unlocked(lock2);
522 521
523 522 /* Tell pidB to exit */
524 523 flock_alert(fdsB[0]);
525 524 flock_cleanup_child(pidB, fdsB);
526 525
527 526 assert_all_unlocked();
528 527
529 528 flock_log(" ok\n");
530 529 }
531 530
532 531
533 532 static void
534 533 flock_test_ofd_sameproc(void)
535 534 {
536 535 lockinfo_t afd1, afd2, afd3;
537 536
538 537 VERIFY3S(flock_copyfil(&flock_fileA, &afd1), ==, 0);
539 538 VERIFY3S(flock_copyfil(&flock_fileA, &afd2), ==, 0);
540 539 VERIFY3S(flock_copyfil(&flock_fileA, &afd3), ==, 0);
541 540
542 541 flock_log("Acquiring first two shared locks...");
543 542 VERIFY3S(flock(afd1.lf_fd, LOCK_SH), ==, 0);
544 543 VERIFY3S(flock(afd2.lf_fd, LOCK_SH), ==, 0);
545 544 assert_read_locked_by(&flock_fileA, -1);
546 545 flock_log(" ok\n");
547 546
548 547 flock_log("Acquiring an exclusive lock should fail w/ EWOULDBLOCK...");
549 548 VERIFY3S(flock(afd3.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
550 549 VERIFY3U(errno, ==, EWOULDBLOCK);
551 550 flock_log(" ok\n");
552 551
553 552 flock_log("Releasing to acquire an exclusive lock...");
554 553 VERIFY3S(flock(afd1.lf_fd, LOCK_UN), ==, 0);
555 554 VERIFY3S(flock(afd2.lf_fd, LOCK_UN), ==, 0);
556 555 flock_log(" ok\n");
557 556
558 557 flock_log("Acquiring an exclusive lock...");
559 558 VERIFY3S(flock(afd3.lf_fd, LOCK_EX), ==, 0);
560 559 assert_write_locked_by(&flock_fileA, -1);
561 560 flock_log(" ok\n");
562 561
563 562 flock_log("Acquiring a shared lock should fail w/ EWOULDBLOCK...");
564 563 VERIFY3S(flock(afd1.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
565 564 VERIFY3U(errno, ==, EWOULDBLOCK);
566 565 VERIFY3S(flock(afd2.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
567 566 VERIFY3U(errno, ==, EWOULDBLOCK);
568 567 flock_log(" ok\n");
569 568
570 569 flock_log("Releasing exclusive lock...");
571 570 VERIFY3S(flock(afd3.lf_fd, LOCK_UN), ==, 0);
572 571 assert_all_unlocked();
573 572 flock_log(" ok\n");
574 573
575 574 flock_rminfo(&afd1);
576 575 flock_rminfo(&afd2);
577 576 flock_rminfo(&afd3);
578 577 }
579 578
580 579
581 580 static void
582 581 flock_runtests(void)
583 582 {
584 583 lock_style_t first, second;
585 584 int i;
586 585
587 586 flock_log("# Exclusive lock tests\n");
588 587 for (first = (lock_style_t)0; first < LSTYLE_LAST; first++) {
589 588 for (second = (lock_style_t)0; second < LSTYLE_LAST; second++) {
590 589 flock_test_exclusive(first, second,
591 590 &flock_fileA, &flock_fileB, B_TRUE);
592 591 flock_test_exclusive(first, second,
593 592 &flock_fileA, &flock_fileB, B_FALSE);
594 593 }
595 594 }
596 595
597 596 flock_log("# Shared lock tests\n");
598 597 for (first = (lock_style_t)0; first < LSTYLE_LAST; first++) {
599 598 for (second = (lock_style_t)0; second < LSTYLE_LAST; second++) {
600 599 flock_test_shared(first, second,
601 600 &flock_fileA, &flock_fileB, B_TRUE);
602 601 flock_test_shared(first, second,
603 602 &flock_fileA, &flock_fileB, B_FALSE);
604 603 }
605 604 }
606 605
607 606 flock_log("# flock(3C) directory lock tests\n");
608 607 flock_test_exclusive(LSTYLE_FLOCK, LSTYLE_FLOCK,
609 608 &flock_dirA, &flock_dirB, B_TRUE);
610 609 flock_test_exclusive(LSTYLE_FLOCK, LSTYLE_FLOCK,
611 610 &flock_dirA, &flock_dirB, B_FALSE);
612 611 flock_test_shared(LSTYLE_FLOCK, LSTYLE_FLOCK,
613 612 &flock_dirA, &flock_dirB, B_TRUE);
614 613 flock_test_shared(LSTYLE_FLOCK, LSTYLE_FLOCK,
615 614 &flock_dirA, &flock_dirB, B_FALSE);
616 615
617 616
618 617 flock_log("# Invalid fcntl(2) parameters tests\n");
619 618 for (i = 0; i < sizeof (cmds) / sizeof (short); i++) {
620 619 flock_test_invalid(&flock_fileA, cmds[i], 200, 0, 0, 0);
621 620 flock_test_invalid(&flock_fileA, cmds[i], -1, 0, 0, 0);
622 621 }
623 622 for (i = 3; i < sizeof (cmds) / sizeof (short); i++) {
624 623 flock_test_invalid(&flock_fileA, cmds[i], F_WRLCK, 1, 0, 0);
625 624 flock_test_invalid(&flock_fileA, cmds[i], F_WRLCK, 0, 1, 0);
626 625 flock_test_invalid(&flock_fileA, cmds[i], F_WRLCK, 0, 0, 1);
627 626 }
628 627 for (i = 0; i < sizeof (cmds64) / sizeof (short); i++) {
629 628 flock_test_invalid64(&flock_fileA, cmds64[i], F_WRLCK, 1, 0, 0);
630 629 flock_test_invalid64(&flock_fileA, cmds64[i], F_WRLCK, 0, 1, 0);
631 630 flock_test_invalid64(&flock_fileA, cmds64[i], F_WRLCK, 0, 0, 1);
632 631 }
633 632
634 633 flock_log("# Testing that multiple OFD locks work in a process\n");
635 634 flock_test_ofd_sameproc();
636 635
637 636 flock_log("# Testing flock(3C) upgrade/downgrade tests\n");
638 637 flock_test_upgrade_downgrade();
639 638 }
640 639
641 640
642 641 int
643 642 main(int argc, char *argv[])
644 643 {
645 644 char *basestr, *suffix, *dirstr, *dirpath;
646 645 pid_t testrunner;
647 646 int exval;
648 647
649 648 LOG = B_TRUE;
650 649
651 650 if (argc < 1) {
652 651 errx(EXIT_FAILURE, "Can't find program name!");
653 652 }
654 653
655 654 dirstr = strdup(argv[0]);
656 655 dirpath = dirname(dirstr);
657 656 basestr = strdup(argv[0]);
658 657 suffix = basename(basestr);
659 658
660 659 while (*suffix != '.' && *suffix != '\0') {
661 660 suffix += 1;
662 661 }
663 662
664 663 if (asprintf(&acqprog, "%s/acquire-lock%s", dirpath, suffix) < 0) {
665 664 errx(EXIT_FAILURE,
666 665 "Can't generate lock acquisition program name!");
667 666 }
668 667
669 668 if (access(acqprog, X_OK) != 0) {
670 669 err(EXIT_FAILURE,
671 670 "Can't run lock acquisition program %s", acqprog);
672 671 }
673 672
674 673 /* Create several lockfiles for testing */
675 674 if (flock_mkfil(&flock_fileA) != 0 ||
676 675 flock_mkfil(&flock_fileB) != 0 ||
677 676 flock_mkdir(&flock_dirA) != 0 ||
678 677 flock_mkdir(&flock_dirB) != 0) {
679 678 exval = 1;
680 679 goto cleanup;
681 680 }
682 681
683 682 /*
684 683 * We run the tests in a child process so that when tests fail
685 684 * we can still clean up our temporary files.
686 685 */
687 686 testrunner = fork();
688 687 if (testrunner == (pid_t)-1) {
689 688 err(EXIT_FAILURE, "Unable to fork to run tests");
690 689 } else if (testrunner == (pid_t)0) {
691 690 flock_runtests();
692 691 return (0);
693 692 }
694 693
695 694 exval = flock_wait(testrunner);
696 695
697 696 cleanup:
698 697 free(basestr);
699 698 free(dirstr);
700 699 flock_rminfo(&flock_fileA);
701 700 flock_rminfo(&flock_fileB);
702 701 flock_rminfo(&flock_dirA);
703 702 flock_rminfo(&flock_dirB);
704 703 return (exval);
705 704 }
↓ open down ↓ |
365 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX