Print this page
| 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
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 13 * Copyright 2016 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_exclusive(lock_style_t, lock_style_t,
64 64 lockinfo_t *, lockinfo_t *, boolean_t);
65 65 static void flock_test_shared(lock_style_t, lock_style_t, lockinfo_t *,
66 66 lockinfo_t *, boolean_t);
67 67 static void flock_test_upgrade_downgrade(void);
68 68
69 69 static char *acqprog = NULL;
70 70
71 71 static lockinfo_t flock_fileA = { "a", NULL, -1 };
72 72 static lockinfo_t flock_fileB = { "b", NULL, -1 };
73 73 static lockinfo_t flock_dirA = { "a", NULL, -1 };
74 74 static lockinfo_t flock_dirB = { "b", NULL, -1 };
75 75
76 76
77 77 static short cmds[8] = {
78 78 F_SETLK, F_SETLKW, F_GETLK,
79 79 F_OFD_SETLK, F_OFD_SETLKW, F_OFD_GETLK,
80 80 F_FLOCK, F_FLOCKW
81 81 };
82 82
83 83
84 84 static void
85 85 flock_kill(pid_t pid)
86 86 {
87 87 while (kill(pid, SIGKILL) == -1) {
88 88 if (errno == EINTR)
89 89 continue;
90 90
91 91 err(EXIT_FAILURE, "kill failed");
92 92 }
93 93 }
94 94
95 95
96 96 static void
97 97 flock_fcntl(lockinfo_t *lf, int cmd, struct flock *fl)
98 98 {
99 99 if (fcntl(lf->lf_fd, cmd, fl) == -1) {
100 100 err(EXIT_FAILURE, "fcntl failed");
101 101 }
102 102 }
103 103
104 104
105 105 static void
106 106 assert_write_locked_by(lockinfo_t *lf, pid_t pid)
107 107 {
108 108 struct flock fl;
109 109
110 110 flock_reinit(&fl, F_WRLCK);
111 111 flock_fcntl(lf, F_GETLK, &fl);
112 112 VERIFY3_IMPL(fl.l_type, ==, F_WRLCK, short);
113 113 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
114 114 VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
115 115
116 116 flock_reinit(&fl, F_WRLCK);
117 117 flock_fcntl(lf, F_OFD_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_RDLCK);
123 123 flock_fcntl(lf, F_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_OFD_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
135 135
136 136 static void
137 137 assert_read_locked_by(lockinfo_t *lf, pid_t pid)
138 138 {
139 139 struct flock fl;
140 140
141 141 flock_reinit(&fl, F_WRLCK);
142 142 flock_fcntl(lf, F_GETLK, &fl);
143 143 VERIFY3_IMPL(fl.l_type, ==, F_RDLCK, short);
144 144 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
145 145 VERIFY3_IMPL(fl.l_pid, ==, pid, pid_t);
146 146
147 147 flock_reinit(&fl, F_WRLCK);
148 148 flock_fcntl(lf, F_OFD_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_RDLCK);
154 154 flock_fcntl(lf, F_GETLK, &fl);
155 155 VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
156 156 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
157 157 VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
158 158
159 159 flock_reinit(&fl, F_RDLCK);
160 160 flock_fcntl(lf, F_OFD_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
166 166 static void
167 167 assert_unlocked(lockinfo_t *lf)
168 168 {
169 169 struct flock fl;
170 170
171 171 flock_reinit(&fl, F_WRLCK);
172 172 flock_fcntl(lf, F_GETLK, &fl);
173 173 VERIFY3_IMPL(fl.l_type, ==, F_UNLCK, short);
174 174 VERIFY3_IMPL(fl.l_sysid, ==, 0, int);
175 175 VERIFY3_IMPL(fl.l_pid, ==, 0, pid_t);
176 176
177 177 flock_reinit(&fl, F_WRLCK);
178 178 flock_fcntl(lf, F_OFD_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_RDLCK);
184 184 flock_fcntl(lf, F_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_OFD_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
196 196
197 197 static void
198 198 assert_all_unlocked(void)
199 199 {
200 200 assert_unlocked(&flock_fileA);
201 201 assert_unlocked(&flock_fileB);
202 202 assert_unlocked(&flock_dirA);
203 203 assert_unlocked(&flock_dirB);
204 204 }
205 205
206 206
207 207 static int
208 208 flock_copyfil(lockinfo_t *src, lockinfo_t *dst)
209 209 {
210 210 dst->lf_name = NULL;
211 211 dst->lf_path = NULL;
212 212 if ((dst->lf_fd = open(src->lf_path, O_RDWR)) == -1) {
213 213 warn("Failed to open %s", src->lf_path);
214 214 return (-1);
215 215 }
216 216
217 217 return (0);
218 218 }
219 219
220 220
221 221 static int
222 222 flock_mkfil(lockinfo_t *lf)
223 223 {
224 224 if (asprintf(&lf->lf_path, LOCKFILE_FMT, lf->lf_name, getpid()) < 0) {
225 225 warnx("Failed to generate lockfile name");
226 226 return (-1);
227 227 }
228 228
229 229 if ((lf->lf_fd = open(lf->lf_path, O_RDWR|O_CREAT, 0600)) == -1) {
230 230 warn("Failed to open %s", lf->lf_path);
231 231 return (-1);
232 232 }
233 233
234 234 return (0);
235 235 }
236 236
237 237
238 238 static int
239 239 flock_mkdir(lockinfo_t *lf)
240 240 {
241 241 if (asprintf(&lf->lf_path, LOCKDIR_FMT, lf->lf_name, getpid()) < 0) {
242 242 warnx("Failed to generate lockfile name");
243 243 return (-1);
244 244 }
245 245
246 246 if (mkdir(lf->lf_path, 0700) == -1) {
247 247 warn("Failed to make %s", lf->lf_path);
248 248 return (-1);
249 249 }
250 250
251 251 if ((lf->lf_fd = open(lf->lf_path, O_RDONLY)) == -1) {
252 252 warn("Failed to open %s", lf->lf_path);
253 253 return (-1);
254 254 }
255 255
256 256 return (0);
257 257 }
258 258
259 259
260 260 static void
261 261 flock_rminfo(lockinfo_t *lf)
262 262 {
263 263 if (lf->lf_fd != -1) {
264 264 (void) close(lf->lf_fd);
265 265 }
266 266 if (lf->lf_path != NULL) {
267 267 (void) unlink(lf->lf_path);
268 268 free(lf->lf_path);
269 269 }
270 270 }
271 271
272 272
273 273 static void
274 274 flock_run(lock_style_t style, boolean_t is_exclusive, lockinfo_t *lf,
275 275 pid_t *pid, int fds[])
276 276 {
277 277 char *stylestr = flock_stylestr(style);
278 278 char *modestr = is_exclusive ? "exclusive" : "shared";
279 279 char *argv[5] = { acqprog, stylestr, modestr, lf->lf_path, NULL };
280 280 int ret = pipe(fds);
281 281 if (ret == -1) {
282 282 err(EXIT_FAILURE, "pipe failed");
283 283 }
284 284
285 285 *pid = fork();
286 286 if (*pid == (pid_t)-1) {
287 287 err(EXIT_FAILURE, "fork failed");
288 288 } else if (*pid == (pid_t)0) {
289 289 /* Set up pipe for communicating with child */
290 290 ret = dup2(fds[1], 0);
291 291 if (ret == -1) {
292 292 err(EXIT_FAILURE, "dup2 failed");
293 293 }
294 294 ret = dup2(fds[1], 1);
295 295 if (ret == -1) {
296 296 err(EXIT_FAILURE, "dup2 failed");
297 297 }
298 298 closefrom(3);
299 299
300 300 (void) execv(acqprog, argv);
301 301 err(EXIT_FAILURE, "Failed to execute %s", acqprog);
302 302 }
303 303 }
304 304
305 305
306 306 static int
307 307 flock_wait(pid_t pid)
308 308 {
309 309 int childstat = 0;
310 310
311 311 while (waitpid(pid, &childstat, 0) == -1) {
312 312 if (errno == EINTR)
313 313 continue;
314 314
315 315 err(EXIT_FAILURE, "Failed to wait on child");
316 316 }
317 317
318 318 if (WIFEXITED(childstat)) {
319 319 return (WEXITSTATUS(childstat));
320 320 } else if (WIFSIGNALED(childstat)) {
321 321 return (1);
322 322 } else {
323 323 abort();
324 324 return (1);
325 325 }
326 326 }
327 327
328 328
329 329 static void
330 330 flock_cleanup_child(pid_t pid, int fds[])
331 331 {
332 332 (void) flock_wait(pid);
333 333 (void) close(fds[0]);
334 334 (void) close(fds[1]);
335 335 }
336 336
337 337
338 338 static void
339 339 flock_test_upgrade_downgrade(void)
340 340 {
341 341 lockinfo_t afd1, afd2, afd3;
342 342 pid_t pid;
343 343 int fds[2];
344 344
345 345 VERIFY3S(flock_copyfil(&flock_fileA, &afd1), ==, 0);
346 346 VERIFY3S(flock_copyfil(&flock_fileA, &afd2), ==, 0);
347 347 VERIFY3S(flock_copyfil(&flock_fileA, &afd3), ==, 0);
348 348
349 349 flock_log("Acquiring shared locks 1, 2 and 3...");
350 350 VERIFY3S(flock(afd1.lf_fd, LOCK_SH), ==, 0);
351 351 VERIFY3S(flock(afd2.lf_fd, LOCK_SH), ==, 0);
352 352 VERIFY3S(flock(afd3.lf_fd, LOCK_SH), ==, 0);
353 353 assert_read_locked_by(&flock_fileA, -1);
354 354 flock_log(" ok\n");
355 355
356 356 flock_log("Upgrading lock 3 should fail w/ EWOULDBLOCK...");
357 357 VERIFY3S(flock(afd3.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
358 358 VERIFY3U(errno, ==, EWOULDBLOCK);
359 359 assert_read_locked_by(&flock_fileA, -1);
360 360 flock_log(" ok\n");
361 361
362 362 flock_log("Upgrading 3 should succeed after releasing locks 1 & 2...");
363 363 VERIFY3S(flock(afd1.lf_fd, LOCK_UN), ==, 0);
364 364 VERIFY3S(flock(afd2.lf_fd, LOCK_UN), ==, 0);
365 365 VERIFY3S(flock(afd3.lf_fd, LOCK_EX), ==, 0);
366 366 assert_write_locked_by(&flock_fileA, -1);
367 367 flock_log(" ok\n");
368 368
369 369
370 370 flock_log("Starting up child, then downgrading lock 3 to shared...");
371 371 flock_run(LSTYLE_FLOCK, B_FALSE, &flock_fileA, &pid, fds);
372 372 VERIFY3_IMPL(flock_nodata(fds[0]), ==, B_TRUE, boolean_t);
373 373 VERIFY3S(flock(afd3.lf_fd, LOCK_SH), ==, 0);
374 374 flock_block(fds[0]);
375 375 assert_read_locked_by(&flock_fileA, -1);
376 376 flock_log(" ok\n");
377 377
378 378 flock_log("Releasing child and upgrading...");
379 379 flock_alert(fds[0]);
380 380 flock_cleanup_child(pid, fds);
381 381 assert_read_locked_by(&flock_fileA, -1);
382 382 VERIFY3S(flock(afd3.lf_fd, LOCK_EX), ==, 0);
383 383 assert_write_locked_by(&flock_fileA, -1);
384 384 flock_log(" ok\n");
385 385
386 386 flock_log("Releasing lock 3...");
387 387 VERIFY3S(flock(afd3.lf_fd, LOCK_UN), ==, 0);
388 388 flock_rminfo(&afd1);
389 389 flock_rminfo(&afd2);
390 390 flock_rminfo(&afd3);
391 391 assert_all_unlocked();
392 392 flock_log(" ok\n");
393 393 }
394 394
395 395
396 396 static void
397 397 flock_test_invalid(lockinfo_t *lf, int cmd, short l_type, short l_whence,
398 398 off_t l_start, off_t l_len)
399 399 {
400 400 struct flock fl = {
401 401 .l_type = l_type,
402 402 .l_whence = l_whence,
403 403 .l_start = l_start,
404 404 .l_len = l_len
405 405 };
406 406
407 407 flock_log("fcntl(fd, %s, { %hd, %hd, %ld, %ld, ... })...",
408 408 flock_cmdname(cmd), l_type, l_whence, l_start, l_len);
409 409 VERIFY3S(fcntl(lf->lf_fd, cmd, &fl), ==, -1);
410 410 VERIFY3U(errno, ==, EINVAL);
411 411 flock_log(" ok\n");
412 412 }
413 413
414 414
415 415 static void
416 416 flock_test_exclusive(lock_style_t styleA, lock_style_t styleB,
417 417 lockinfo_t *lock1, lockinfo_t *lock2, boolean_t kill_firstborn)
418 418 {
419 419 pid_t pidA, pidB;
420 420 int fdsA[2], fdsB[2];
421 421
422 422 flock_log("Running %s + %s tests (%s)...",
423 423 flock_stylename(styleA), flock_stylename(styleB),
424 424 kill_firstborn ? "kill child" : "child exits");
425 425
426 426 /* Create child, and wait for it to acquire the lock */
427 427 flock_run(styleA, B_TRUE, lock1, &pidA, fdsA);
428 428 flock_block(fdsA[0]);
429 429
430 430 /* Create second child, which shouldn't acquire & signal */
431 431 flock_run(styleB, B_TRUE, lock1, &pidB, fdsB);
432 432 VERIFY3_IMPL(flock_nodata(fdsB[0]), ==, B_TRUE, boolean_t);
433 433
434 434 /* lock1 is blocked for reading and writing */
435 435 assert_write_locked_by(lock1, styleA == LSTYLE_POSIX ? pidA : -1);
436 436 assert_unlocked(lock2);
437 437
438 438 /* Tell pidA to exit */
439 439 if (kill_firstborn) {
440 440 flock_kill(pidA);
441 441 } else {
442 442 flock_alert(fdsA[0]);
443 443 }
444 444 flock_cleanup_child(pidA, fdsA);
445 445
446 446 /* Wait for pidB to signal us */
447 447 flock_block(fdsB[0]);
448 448
449 449 /* lock1 is blocked for reading and writing */
450 450 assert_write_locked_by(lock1, styleB == LSTYLE_POSIX ? pidB : -1);
451 451 assert_unlocked(lock2);
452 452
453 453 /* Tell pidB to exit */
454 454 flock_alert(fdsB[0]);
455 455
456 456 flock_cleanup_child(pidB, fdsB);
457 457
458 458 /*
459 459 * Tests after child has released lock
460 460 */
461 461 assert_all_unlocked();
462 462
463 463 flock_log(" ok\n");
464 464 }
465 465
466 466
467 467 static void
468 468 flock_test_shared(lock_style_t styleA, lock_style_t styleB,
469 469 lockinfo_t *lock1, lockinfo_t *lock2, boolean_t kill_firstborn)
470 470 {
471 471 pid_t pidA, pidB;
472 472 int fdsA[2], fdsB[2];
473 473
474 474 flock_log("Running %s + %s tests (%s)...",
475 475 flock_stylename(styleA), flock_stylename(styleB),
476 476 kill_firstborn ? "kill child" : "child exits");
477 477
478 478 /* Create children, and wait for it to acquire the lock */
479 479 flock_run(styleB, B_FALSE, lock1, &pidB, fdsB);
480 480 flock_block(fdsB[0]);
481 481 flock_run(styleA, B_FALSE, lock1, &pidA, fdsA);
482 482 flock_block(fdsA[0]);
483 483
484 484 /* testfileA is only blocked for writing */
485 485 assert_read_locked_by(lock1, styleA == LSTYLE_POSIX ? pidA : -1);
486 486 assert_unlocked(lock2);
487 487
488 488 /* Tell pidA to exit */
489 489 if (kill_firstborn) {
490 490 flock_kill(pidA);
491 491 } else {
492 492 flock_alert(fdsA[0]);
493 493 }
494 494 flock_cleanup_child(pidA, fdsA);
495 495
496 496 /* testfileA is still blocked for writing by pidB */
497 497 assert_read_locked_by(lock1, styleB == LSTYLE_POSIX ? pidB : -1);
498 498 assert_unlocked(lock2);
499 499
500 500 /* Tell pidB to exit */
501 501 flock_alert(fdsB[0]);
502 502 flock_cleanup_child(pidB, fdsB);
503 503
504 504 assert_all_unlocked();
505 505
506 506 flock_log(" ok\n");
507 507 }
508 508
509 509
510 510 static void
511 511 flock_test_ofd_sameproc(void)
512 512 {
513 513 lockinfo_t afd1, afd2, afd3;
514 514
515 515 VERIFY3S(flock_copyfil(&flock_fileA, &afd1), ==, 0);
516 516 VERIFY3S(flock_copyfil(&flock_fileA, &afd2), ==, 0);
517 517 VERIFY3S(flock_copyfil(&flock_fileA, &afd3), ==, 0);
518 518
519 519 flock_log("Acquiring first two shared locks...");
520 520 VERIFY3S(flock(afd1.lf_fd, LOCK_SH), ==, 0);
521 521 VERIFY3S(flock(afd2.lf_fd, LOCK_SH), ==, 0);
522 522 assert_read_locked_by(&flock_fileA, -1);
523 523 flock_log(" ok\n");
524 524
525 525 flock_log("Acquiring an exclusive lock should fail w/ EWOULDBLOCK...");
526 526 VERIFY3S(flock(afd3.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
527 527 VERIFY3U(errno, ==, EWOULDBLOCK);
528 528 flock_log(" ok\n");
529 529
530 530 flock_log("Releasing to acquire an exclusive lock...");
531 531 VERIFY3S(flock(afd1.lf_fd, LOCK_UN), ==, 0);
532 532 VERIFY3S(flock(afd2.lf_fd, LOCK_UN), ==, 0);
533 533 flock_log(" ok\n");
534 534
535 535 flock_log("Acquiring an exclusive lock...");
536 536 VERIFY3S(flock(afd3.lf_fd, LOCK_EX), ==, 0);
537 537 assert_write_locked_by(&flock_fileA, -1);
538 538 flock_log(" ok\n");
539 539
540 540 flock_log("Acquiring a shared lock should fail w/ EWOULDBLOCK...");
541 541 VERIFY3S(flock(afd1.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
542 542 VERIFY3U(errno, ==, EWOULDBLOCK);
543 543 VERIFY3S(flock(afd2.lf_fd, LOCK_EX|LOCK_NB), ==, -1);
544 544 VERIFY3U(errno, ==, EWOULDBLOCK);
545 545 flock_log(" ok\n");
546 546
547 547 flock_log("Releasing exclusive lock...");
548 548 VERIFY3S(flock(afd3.lf_fd, LOCK_UN), ==, 0);
549 549 assert_all_unlocked();
550 550 flock_log(" ok\n");
551 551
552 552 flock_rminfo(&afd1);
553 553 flock_rminfo(&afd2);
554 554 flock_rminfo(&afd3);
555 555 }
556 556
557 557
558 558 static void
559 559 flock_runtests(void)
560 560 {
561 561 lock_style_t first, second;
562 562 int i;
563 563
564 564 flock_log("# Exclusive lock tests\n");
565 565 for (first = (lock_style_t)0; first < LSTYLE_LAST; first++) {
566 566 for (second = (lock_style_t)0; second < LSTYLE_LAST; second++) {
567 567 flock_test_exclusive(first, second,
568 568 &flock_fileA, &flock_fileB, B_TRUE);
569 569 flock_test_exclusive(first, second,
570 570 &flock_fileA, &flock_fileB, B_FALSE);
571 571 }
572 572 }
573 573
574 574 flock_log("# Shared lock tests\n");
575 575 for (first = (lock_style_t)0; first < LSTYLE_LAST; first++) {
576 576 for (second = (lock_style_t)0; second < LSTYLE_LAST; second++) {
577 577 flock_test_shared(first, second,
578 578 &flock_fileA, &flock_fileB, B_TRUE);
579 579 flock_test_shared(first, second,
580 580 &flock_fileA, &flock_fileB, B_FALSE);
581 581 }
582 582 }
583 583
584 584 flock_log("# flock(3C) directory lock tests\n");
585 585 flock_test_exclusive(LSTYLE_FLOCK, LSTYLE_FLOCK,
586 586 &flock_dirA, &flock_dirB, B_TRUE);
587 587 flock_test_exclusive(LSTYLE_FLOCK, LSTYLE_FLOCK,
588 588 &flock_dirA, &flock_dirB, B_FALSE);
589 589 flock_test_shared(LSTYLE_FLOCK, LSTYLE_FLOCK,
590 590 &flock_dirA, &flock_dirB, B_TRUE);
591 591 flock_test_shared(LSTYLE_FLOCK, LSTYLE_FLOCK,
592 592 &flock_dirA, &flock_dirB, B_FALSE);
593 593
594 594
595 595 flock_log("# Invalid fcntl(2) parameters tests\n");
596 596 for (i = 0; i < sizeof (cmds) / sizeof (short); i++) {
597 597 flock_test_invalid(&flock_fileA, cmds[i], 200, 0, 0, 0);
598 598 flock_test_invalid(&flock_fileA, cmds[i], -1, 0, 0, 0);
599 599 }
600 600 for (i = 3; i < sizeof (cmds) / sizeof (short); i++) {
601 601 flock_test_invalid(&flock_fileA, cmds[i], F_WRLCK, 1, 0, 0);
602 602 flock_test_invalid(&flock_fileA, cmds[i], F_WRLCK, 0, 1, 0);
603 603 flock_test_invalid(&flock_fileA, cmds[i], F_WRLCK, 0, 0, 1);
604 604 }
605 605
606 606 flock_log("# Testing that multiple OFD locks work in a process\n");
607 607 flock_test_ofd_sameproc();
608 608
609 609 flock_log("# Testing flock(3C) upgrade/downgrade tests\n");
610 610 flock_test_upgrade_downgrade();
611 611 }
612 612
613 613
614 614 int
615 615 main(int argc, char *argv[])
616 616 {
617 617 char *basestr, *suffix, *dirstr, *dirpath;
618 618 pid_t testrunner;
619 619 int exval;
620 620
621 621 LOG = B_TRUE;
622 622
623 623 if (argc < 1) {
624 624 errx(EXIT_FAILURE, "Can't find program name!");
625 625 }
626 626
627 627 dirstr = strdup(argv[0]);
628 628 dirpath = dirname(dirstr);
629 629 basestr = strdup(argv[0]);
630 630 suffix = basename(basestr);
631 631
632 632 while (*suffix != '.' && *suffix != '\0') {
633 633 suffix += 1;
634 634 }
635 635
636 636 if (asprintf(&acqprog, "%s/acquire-lock%s", dirpath, suffix) < 0) {
637 637 errx(EXIT_FAILURE,
638 638 "Can't generate lock acquisition program name!");
639 639 }
640 640
641 641 if (access(acqprog, X_OK) != 0) {
642 642 err(EXIT_FAILURE,
643 643 "Can't run lock acquisition program %s", acqprog);
644 644 }
645 645
646 646 /* Create several lockfiles for testing */
647 647 if (flock_mkfil(&flock_fileA) != 0 ||
648 648 flock_mkfil(&flock_fileB) != 0 ||
649 649 flock_mkdir(&flock_dirA) != 0 ||
650 650 flock_mkdir(&flock_dirB) != 0) {
651 651 exval = 1;
652 652 goto cleanup;
653 653 }
654 654
655 655 /*
656 656 * We run the tests in a child process so that when tests fail
657 657 * we can still clean up our temporary files.
658 658 */
659 659 testrunner = fork();
660 660 if (testrunner == (pid_t)-1) {
661 661 err(EXIT_FAILURE, "Unable to fork to run tests");
662 662 } else if (testrunner == (pid_t)0) {
663 663 flock_runtests();
664 664 return (0);
665 665 }
666 666
667 667 exval = flock_wait(testrunner);
668 668
669 669 cleanup:
670 670 free(basestr);
671 671 free(dirstr);
672 672 flock_rminfo(&flock_fileA);
673 673 flock_rminfo(&flock_fileB);
674 674 flock_rminfo(&flock_dirA);
675 675 flock_rminfo(&flock_dirB);
676 676 return (exval);
677 677 }
|
↓ open down ↓ |
677 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX