1 /*
2 *
3 * Copyright (c) International Business Machines Corp., 2001
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13 * the GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 /*
21 * NAME
22 * fcntl14.c
23 *
24 * DESCRIPTION
25 * File locking test cases for fcntl. In Linux, S_ENFMT is not implemented
26 * in the kernel. However all standard Unix kernels define S_ENFMT as
27 * S_ISGID. So this test defines S_ENFMT as S_ISGID.
28 *
29 * ALGORITHM
30 * Various test cases are used to lock a file opened without mandatory
31 * locking, with mandatory locking and mandatory locking with NOBLOCK
32 *
33 * USAGE
34 * fcntl14
35 *
36 * HISTORY
37 * 07/2001 Ported by Wayne Boyer
38 *
39 * RESTRICTIONS
40 * None
41 */
42 #define _GNU_SOURCE 1
43 #include <fcntl.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <signal.h>
47 #include <errno.h>
48 #include <sys/wait.h>
49 #include <inttypes.h>
50 #include "test.h"
51 #include "safe_macros.h"
52
53 #define SKIP 0x0c00
54 #if SKIP == F_RDLCK || SKIP== F_WRLCK
55 #error invalid value for SKIP, must be distinct from F_RDLCK and F_WRLCK
56 #endif
57 #ifndef S_ENFMT
58 #define S_ENFMT S_ISGID
59 #endif
60
61 /* NOBLOCK - immediate success */
62 #define NOBLOCK 2
63
64 /* WILLBLOCK - blocks, then succeeds (parent must unlock records) */
65 #define WILLBLOCK 3
66
67 #define TIME_OUT 60
68
69 typedef struct {
70 short a_type;
71 short a_whence;
72 long a_start;
73 long a_len;
74 short b_type; /* SKIP means suppress fcntl call */
75 short b_whence;
76 long b_start;
77 long b_len;
78 short c_type;
79 int c_whence;
80 long c_start;
81 long c_len;
82 short c_flag;
83 } testcase;
84
85 static testcase testcases[] = {
86 /* Test cases: entire boundary */
87 /* #1 Parent making a write lock on entire file */
88 {F_WRLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L,
89 /* Child attempting a read lock on entire file */
90 F_RDLCK, 0, 0L, 0L, WILLBLOCK},
91
92 /* #2 Parent making a write lock on entire file */
93 {F_WRLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L,
94 /* Child attempting a write lock on entire file */
95 F_WRLCK, 0, 0L, 0L, WILLBLOCK},
96
97 /* #3 Parent making a read lock on entire file */
98 {F_RDLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L,
99 /* Child attempting a read lock on entire file */
100 F_RDLCK, 0, 0L, 0L, NOBLOCK},
101
102 /* #4 Parent making a read lock on entire file */
103 {F_RDLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L,
104 /* Child attempting a write lock on entire file */
105 F_WRLCK, 0, 0L, 0L, WILLBLOCK},
106
107 /* Test case: start boundary */
108 /* #5 Parent making a write lock on entire file */
109 {F_WRLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L,
110 /*
111 * Child attempting a read lock from beginning of
112 * file for 5 bytes
113 */
114 F_RDLCK, 0, 0L, 5L, WILLBLOCK},
115
116 /* #6 Parent making a write lock on entire file */
117 {F_WRLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L,
118 /*
119 * Child attempting a write lock from beginning of
120 * file for 5 bytes
121 */
122 F_WRLCK, 0, 0L, 5L, WILLBLOCK},
123
124 /* #7 Parent making a read lock on entire file */
125 {F_RDLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L,
126 /*
127 * Child attempting a read lock from beginning of
128 * file for 5 bytes
129 */
130 F_RDLCK, 0, 0L, 5L, NOBLOCK},
131
132 /* #8 Parent making a read lock on entire file */
133 {F_RDLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L,
134 /*
135 * Child attempting a write lock from beginning of
136 * file for 5 bytes
137 */
138 F_WRLCK, 0, 0L, 5L, WILLBLOCK},
139
140 /* Test cases: end boundary */
141 /* #9 Parent making a write lock on entire file */
142 {F_WRLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L,
143 /* Child attempting a read lock from byte 7 to end of file */
144 F_RDLCK, 0, 7L, 0L, WILLBLOCK},
145
146 /* #10 Parent making a write lock on entire file */
147 {F_WRLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L,
148 /* Child attempting a write lock from byte 7 to end of file */
149 F_WRLCK, 0, 7L, 0L, WILLBLOCK},
150
151 /* #11 Parent making a read lock on entire file */
152 {F_RDLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L,
153 /* Child attempting a read lock from byte 7 to end of file */
154 F_RDLCK, 0, 7L, 0L, NOBLOCK},
155
156 /* #12 Parent making a read lock on entire file */
157 {F_RDLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L,
158 /* Child attempting a write lock from byte 7 to end of file */
159 F_WRLCK, 0, 7L, 0L, WILLBLOCK},
160
161 /* Test cases: entire boundary ( less than entire file) */
162 /*
163 * #13 Parent making a write lock from beginning of
164 * file for 5 bytes
165 */
166 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
167 /*
168 * Child attempting a read lock from beginning of
169 * file for 5 bytes
170 */
171 F_RDLCK, 0, 0L, 5L, WILLBLOCK},
172
173 /*
174 * #14 Parent making a write lock from beginning of file
175 * for 5 bytes
176 */
177 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
178 /*
179 * Child attempting a write lock from beginning of
180 * file for 5 bytes
181 */
182 F_WRLCK, 0, 0L, 5L, WILLBLOCK},
183
184 /*
185 * #15 Parent making a read lock from beginning of
186 * file for 5 bytes
187 */
188 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
189 /*
190 * Child attempting a read lock from beginning of
191 * file for 5 bytes
192 */
193 F_RDLCK, 0, 0L, 5L, NOBLOCK},
194
195 /*
196 * #16 Parent making a read lock from beginning of
197 * file for 5 bytes
198 */
199 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
200 /*
201 * Child attempting a write lock from beginning
202 * of file for 5 bytes
203 */
204 F_WRLCK, 0, 0L, 5L, WILLBLOCK},
205
206 /* Test cases: inside boundary */
207 /*
208 * #17 Parent making a write lock from beginning
209 * of file for 5 bytes
210 */
211 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
212 /* Child attempting a read lock from byte 2 to byte 4 */
213 F_RDLCK, 0, 1L, 3L, WILLBLOCK},
214
215 /*
216 * #18 Parent making a write lock from beginning of
217 * file for 5 bytes
218 */
219 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
220 /* Child attempting a write lock from byte 2 to byte 4 */
221 F_WRLCK, 0, 1L, 3L, WILLBLOCK},
222
223 /*
224 * #19 Parent making a read lock from beginning of
225 * file for 5 bytes
226 */
227 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
228 /* Child attempting a read lock from byte 2 to byte 4 */
229 F_RDLCK, 0, 1L, 3L, NOBLOCK},
230
231 /*
232 * #20 Parent making a read lock from beginning of
233 * file for 5 bytes
234 */
235 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
236 /* Child attempting a write lock from byte 2 to byte 4 */
237 F_WRLCK, 0, 1L, 3L, WILLBLOCK},
238
239 /* Test cases: cross boundary (inside to after) */
240 /*
241 * #21 Parent making a write lock from beginning of
242 * file for 5 bytes
243 */
244 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
245 /* Child attempting a read lock from byte 3 to byte 7 */
246 F_RDLCK, 0, 2L, 5L, WILLBLOCK},
247
248 /*
249 * #22 Parent making a write lock from beginning
250 * of file for 5 bytes
251 */
252 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
253 /* Child attempting a write lock from byte 3 to byte 7 */
254 F_WRLCK, 0, 2L, 5L, WILLBLOCK},
255
256 /*
257 * #23 Parent making a read lock from beginning of
258 * file for 5 bytes
259 */
260 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
261 /* Child attempting a read lock from byte 3 to byte 7 */
262 F_RDLCK, 0, 2L, 5L, NOBLOCK},
263
264 /*
265 * #24 Parent making a read lock from beginning of
266 * file for 5 bytes
267 */
268 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
269 /* Child attempting a write lock from byte 3 to byte 7 */
270 F_WRLCK, 0, 2L, 5L, WILLBLOCK},
271
272 /* Test cases: outside boundary (after) */
273
274 /*
275 * #25 Parent making a write lock from beginning of
276 * file for 5 bytes
277 */
278 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
279 /* Child attempting a read lock from byte 7 to end of file */
280 F_RDLCK, 0, 6L, 0L, NOBLOCK},
281
282 /*
283 * #26 Parent making a write lock from beginning of
284 * file for 5 bytes
285 */
286 {F_WRLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
287 /* Child attempting a write lock from byte 7 to end of file */
288 F_WRLCK, 0, 6L, 0L, NOBLOCK},
289
290 /*
291 * #27 Parent making a read lock from beginning of
292 * file for 5 bytes
293 */
294 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
295 /* Child attempting a read lock from byte 7 to end of file */
296 F_RDLCK, 0, 6L, 0L, NOBLOCK},
297
298 /*
299 * #28 Parent making a read lock from beginning of
300 * file for 5 bytes
301 */
302 {F_RDLCK, 0, 0L, 5L, SKIP, 0, 0L, 0L,
303 /* Child attempting a write lock from byte 7 to end of file */
304 F_WRLCK, 0, 6L, 0L, NOBLOCK},
305
306 /* Test cases: outside boundary (before) */
307
308 /* #29 Parent making a write lock from byte 3 to byte 7 */
309 {F_WRLCK, 0, 2L, 5L, SKIP, 0, 0L, 0L,
310 /* Child attempting a read lock from beginning of file to byte 2 */
311 F_RDLCK, 0, 0L, 2L, NOBLOCK},
312
313 /* #30 Parent making a write lock from byte 3 to byte 7 */
314 {F_WRLCK, 0, 2L, 5L, SKIP, 0, 0L, 0L,
315 /* Child attempting a write lock from beginning of file to byte 2 */
316 F_WRLCK, 0, 0L, 2L, NOBLOCK},
317
318 /* #31 Parent making a write lock from byte 3 to byte 7 */
319 {F_RDLCK, 0, 2L, 5L, SKIP, 0, 0L, 0L,
320 /* Child attempting a read lock from beginning of file to byte 2 */
321 F_RDLCK, 0, 0L, 2L, NOBLOCK},
322
323 /* #32 Parent making a write lock from byte 3 to byte 7 */
324 {F_RDLCK, 0, 2L, 5L, SKIP, 0, 0L, 0L,
325 /* Child attempting a write lock from beginning of file to byte 2 */
326 F_WRLCK, 0, 0L, 2L, NOBLOCK},
327
328 /* Test cases: cross boundary (before to inside) */
329 /* #33 Parent making a write lock from byte 5 to end of file */
330 {F_WRLCK, 0, 4L, 0L, SKIP, 0, 0L, 0L,
331 /* Child attempting a read lock from byte 3 to byte 7 */
332 F_RDLCK, 0, 2L, 5L, WILLBLOCK},
333
334 /* #34 Parent making a write lock from byte 5 to end of file */
335 {F_WRLCK, 0, 4L, 0L, SKIP, 0, 0L, 0L,
336 /* Child attempting a write lock from byte 3 to byte 7 */
337 F_WRLCK, 0, 2L, 5L, WILLBLOCK},
338
339 /* #35 Parent making a read lock from byte 5 to end of file */
340 {F_RDLCK, 0, 4L, 0L, SKIP, 0, 0L, 0L,
341 /* Child attempting a read lock from byte 3 to byte 7 */
342 F_RDLCK, 0, 2L, 5L, NOBLOCK},
343
344 /* #36 Parent making a read lock from byte 5 to end of file */
345 {F_RDLCK, 0, 4L, 0L, SKIP, 0, 0L, 0L,
346 /* Child attempting a write lock from byte 3 to byte 7 */
347 F_WRLCK, 0, 2L, 5L, WILLBLOCK},
348
349 /* Start of negative L_start and L_len test cases */
350 /*
351 * #37 Parent making write lock from byte 2 to byte 3
352 * with L_start = -3
353 */
354 {F_WRLCK, 1, -3L, 2L, SKIP, 0, 0L, 0L,
355 /* Child attempting write lock on byte 1 */
356 F_WRLCK, 0, 1L, 1L, NOBLOCK},
357
358 /*
359 * #38 Parent making write lock from byte 2 to byte 3
360 * with L_start = -3
361 */
362 {F_WRLCK, 1, -3L, 2L, SKIP, 0, 0L, 0L,
363 /* Child attempting write lock on byte 4 */
364 F_WRLCK, 0, 4L, 1L, NOBLOCK},
365
366 /*
367 * #39 Parent making write lock from byte 2 to byte 3
368 * with L_start = -3
369 */
370 {F_WRLCK, 1, -3L, 2L, SKIP, 0, 0L, 0L,
371 /* Child attempting write lock on byte 2 */
372 F_WRLCK, 0, 2L, 1L, WILLBLOCK},
373
374 /*
375 * #40 Parent making write lock from byte 2 to byte 3
376 * with L_start = -3
377 */
378 {F_WRLCK, 1, -3L, 2L, SKIP, 0, 0L, 0L,
379 /* Child attempting write lock on byte 3 */
380 F_WRLCK, 0, 3L, 1L, WILLBLOCK},
381
382 /*
383 * #41 Parent making write lock from byte 2 to byte 6
384 * with L_start = -3
385 */
386 {F_WRLCK, 1, -3L, 5L, SKIP, 0, 0L, 0L,
387 /* Child attempting write lock on byte 1 */
388 F_WRLCK, 0, 1L, 1L, NOBLOCK},
389
390 /*
391 * #42 Parent making write lock from byte 2 to byte 6
392 * with L_start = -3
393 */
394 {F_WRLCK, 1, -3L, 5L, SKIP, 0, 0L, 0L,
395 /* Child attempting write lock on byte 7 */
396 F_WRLCK, 0, 1L, 1L, NOBLOCK},
397
398 /*
399 * #43 Parent making write lock from byte 2 to byte 6
400 * with L_start = -3
401 */
402 {F_WRLCK, 1, -3L, 5L, SKIP, 0, 0L, 0L,
403 /* Child attempting write lock on byte 2 */
404 F_WRLCK, 0, 2L, 1L, WILLBLOCK},
405
406 /*
407 * #44 Parent making write lock from byte 2 to byte 6
408 * with L_start = -3
409 */
410 {F_WRLCK, 1, -3L, 5L, SKIP, 0, 0L, 0L,
411 /* Child attempting write lock on byte 5 */
412 F_WRLCK, 0, 5L, 1L, WILLBLOCK},
413
414 /*
415 * #45 Parent making write lock from byte 2 to byte 6
416 * with L_start = -3
417 */
418 {F_WRLCK, 1, -3L, 5L, SKIP, 0, 0L, 0L,
419 /* Child attempting write lock on byte 6 */
420 F_WRLCK, 0, 6L, 1L, WILLBLOCK},
421
422 /*
423 * #46 Parent making write lock from byte 2 to byte 3 with
424 * L_start = -2 and L_len = -2
425 */
426 {F_WRLCK, 1, 2L, -2L, SKIP, 0, 0L, 0L,
427 /* Child attempting write lock on byte 1 */
428 F_WRLCK, 0, 1L, 1L, NOBLOCK},
429
430 /*
431 * #47 Parent making write lock from byte 2 to byte 3 with
432 * L_start = -2 and L_len = -2
433 */
434 {F_WRLCK, 1, -2L, -2L, SKIP, 0, 0L, 0L,
435 /* Child attempting write lock on byte 4 */
436 F_WRLCK, 0, 4L, 1L, NOBLOCK},
437
438 /*
439 * #48 Parent making write lock from byte 2 to byte 3 with
440 * L_start = -2 and L_len = -2
441 */
442 {F_WRLCK, 1, -2L, -2L, SKIP, 0, 0L, 0L,
443 /* Child attempting write lock on byte 2 */
444 F_WRLCK, 0, 2L, 1L, WILLBLOCK},
445
446 /*
447 * #49 Parent making write lock from byte 2 to byte 3 with
448 * L_start = -2 and L_len = -2
449 */
450 {F_WRLCK, 1, -2L, -2L, SKIP, 0, 0L, 0L,
451 /* Child attempting write lock on byte 3 */
452 F_WRLCK, 0, 3L, 1L, WILLBLOCK},
453
454 /*
455 * #50 Parent making write lock from byte 6 to byte 7 with
456 * L_start = 2 and L_len = -2
457 */
458 {F_WRLCK, 1, 2L, -2L, SKIP, 0, 0L, 0L,
459 /* Child attempting write lock on byte 5 */
460 F_WRLCK, 0, 5L, 1L, NOBLOCK},
461
462 /*
463 * #51 Parent making write lock from byte 6 to byte 7 with
464 * L_start = 2 and L_len = -2
465 */
466 {F_WRLCK, 1, 2L, -2L, SKIP, 0, 0L, 0L,
467 /* Child attempting write lock on byte 8 */
468 F_WRLCK, 0, 8L, 1L, NOBLOCK},
469
470 /*
471 * #52 Parent making write lock from byte 6 to byte 7 with
472 * L_start = 2 and L_len = -2
473 */
474 {F_WRLCK, 1, 2L, -2L, SKIP, 0, 0L, 0L,
475 /* Child attempting write lock on byte 6 */
476 F_WRLCK, 0, 6L, 1L, WILLBLOCK},
477
478 /*
479 * #53 Parent making write lock from byte 6 to byte 7 with
480 * L_start = 2 and L_len = -2
481 */
482 {F_WRLCK, 1, 2L, -2L, SKIP, 0, 0L, 0L,
483 /* Child attempting write lock on byte 7 */
484 F_WRLCK, 0, 7L, 1L, WILLBLOCK},
485
486 /*
487 * #54 Parent making write lock from byte 3 to byte 7 with
488 * L_start = 2 and L_len = -5
489 */
490 {F_WRLCK, 1, 2L, -5L, SKIP, 0, 0L, 0L,
491 /* Child attempting write lock on byte 2 */
492 F_WRLCK, 0, 2L, 1L, NOBLOCK},
493
494 /*
495 * #55 Parent making write lock from byte 3 to byte 7 with
496 * L_start = 2 and L_len = -5
497 */
498 {F_WRLCK, 1, 2L, -5L, SKIP, 0, 0L, 0L,
499 /* Child attempting write lock on byte 8 */
500 F_WRLCK, 0, 8L, 1L, NOBLOCK},
501
502 /*
503 * #56 Parent making write lock from byte 3 to byte 7 with
504 * L_start = 2 and L_len = -5
505 */
506 {F_WRLCK, 1, 2L, -5L, SKIP, 0, 0L, 0L,
507 /* Child attempting write lock on byte 3 */
508 F_WRLCK, 0, 3L, 1L, WILLBLOCK},
509
510 /*
511 * #57 Parent making write lock from byte 3 to byte 7 with
512 * L_start = 2 and L_len = -5
513 */
514 {F_WRLCK, 1, 2L, -5L, SKIP, 0, 0L, 0L,
515 /* Child attempting write lock on byte 5 */
516 F_WRLCK, 0, 5L, 1L, WILLBLOCK},
517
518 /*
519 * #58 Parent making write lock from byte 3 to byte 7 with
520 * L_start = 2 and L_len = -5
521 */
522 {F_WRLCK, 1, 2L, -5L, SKIP, 0, 0L, 0L,
523 /* Child attempting write lock on byte 7 */
524 F_WRLCK, 0, 7L, 1L, WILLBLOCK},
525
526 /* Test case for block 4 */
527 /* #59 Parent making write lock on entire file */
528 {F_WRLCK, 0, 0L, 0L, SKIP, 0, 0L, 0L,
529 /* Child attempting write lock on byte 15 to end of file */
530 F_WRLCK, 0, 15L, 0L, WILLBLOCK},
531 };
532
533 static testcase *thiscase;
534 static struct flock flock;
535 static int parent, child, status, fail = 0;
536 static int got1 = 0;
537 static int fd;
538 static int test;
539 static char tmpname[40];
540
541 #define FILEDATA "ten bytes!"
542
543 void catch1(int sig);
544 void catch_alarm(int sig);
545
546 char *TCID = "fcntl14";
547 int TST_TOTAL = 1;
548 int NO_NFS = 1;
549
550 #ifdef UCLINUX
551 static char *argv0;
552 #endif
553
cleanup(void)554 void cleanup(void)
555 {
556 tst_rmdir();
557 }
558
setup(void)559 void setup(void)
560 {
561 struct sigaction act;
562
563 tst_sig(FORK, DEF_HANDLER, cleanup);
564 signal(SIGHUP, SIG_IGN);
565 umask(0);
566 TEST_PAUSE;
567 tst_tmpdir();
568 parent = getpid();
569
570 sprintf(tmpname, "fcntl2.%d", parent);
571
572 /* setup signal handler for signal from child */
573 memset(&act, 0, sizeof(act));
574 act.sa_handler = catch1;
575 sigemptyset(&act.sa_mask);
576 sigaddset(&act.sa_mask, SIGUSR1);
577 if ((sigaction(SIGUSR1, &act, NULL)) < 0) {
578 tst_resm(TFAIL, "SIGUSR1 signal setup failed, errno = %d",
579 errno);
580 cleanup();
581 }
582
583 memset(&act, 0, sizeof(act));
584 act.sa_handler = catch_alarm;
585 sigemptyset(&act.sa_mask);
586 sigaddset(&act.sa_mask, SIGALRM);
587 if ((sigaction(SIGALRM, &act, NULL)) < 0) {
588 tst_resm(TFAIL, "SIGALRM signal setup failed");
589 cleanup();
590 }
591 }
592
wake_parent(void)593 void wake_parent(void)
594 {
595 if ((kill(parent, SIGUSR1)) < 0) {
596 tst_resm(TFAIL, "Attempt to send signal to parent " "failed");
597 tst_resm(TFAIL, "Test case %d, errno = %d", test + 1, errno);
598 fail = 1;
599 }
600 }
601
do_usleep_child(void)602 void do_usleep_child(void)
603 {
604 usleep(100000); /* XXX how long is long enough? */
605 wake_parent();
606 exit(0);
607 }
608
dochild(void)609 void dochild(void)
610 {
611 int rc;
612 pid_t pid;
613
614 flock.l_type = thiscase->c_type;
615 flock.l_whence = thiscase->c_whence;
616 flock.l_start = thiscase->c_start;
617 flock.l_len = thiscase->c_len;
618 flock.l_pid = 0;
619 fail = 0;
620
621 /*
622 * Check to see if child lock will succeed. If it will, FLOCK
623 * structure will return with l_type changed to F_UNLCK. If it will
624 * not, the parent pid will be returned in l_pid and the type of
625 * lock that will block it in l_type.
626 */
627 if ((rc = fcntl(fd, F_GETLK, &flock)) < 0) {
628 tst_resm(TFAIL, "Attempt to check lock status failed");
629 tst_resm(TFAIL, "Test case %d, errno = %d", test + 1, errno);
630 fail = 1;
631 } else {
632
633 if ((thiscase->c_flag) == NOBLOCK) {
634 if (flock.l_type != F_UNLCK) {
635 tst_resm(TFAIL,
636 "Test case %d, GETLK: type = %d, "
637 "%d was expected", test + 1,
638 flock.l_type, F_UNLCK);
639 fail = 1;
640 }
641
642 if (flock.l_whence != thiscase->c_whence) {
643 tst_resm(TFAIL,
644 "Test case %d, GETLK: whence = %d, "
645 "should have remained %d", test + 1,
646 flock.l_whence, thiscase->c_whence);
647 fail = 1;
648 }
649
650 if (flock.l_start != thiscase->c_start) {
651 tst_resm(TFAIL,
652 "Test case %d, GETLK: start = %" PRId64
653 ", " "should have remained %" PRId64,
654 test + 1, (int64_t) flock.l_start,
655 (int64_t) thiscase->c_start);
656 fail = 1;
657 }
658
659 if (flock.l_len != thiscase->c_len) {
660 tst_resm(TFAIL,
661 "Test case %d, GETLK: len = %" PRId64
662 ", " "should have remained %" PRId64,
663 test + 1, (int64_t) flock.l_len,
664 (int64_t) thiscase->c_len);
665 fail = 1;
666 }
667
668 if (flock.l_pid != 0) {
669 tst_resm(TFAIL,
670 "Test case %d, GETLK: pid = %d, "
671 "should have remained 0", test + 1,
672 flock.l_pid);
673 fail = 1;
674 }
675 } else {
676 if (flock.l_pid != parent) {
677 tst_resm(TFAIL,
678 "Test case %d, GETLK: pid = %d, "
679 "should be parent's id of %d",
680 test + 1, flock.l_pid, parent);
681 fail = 1;
682 }
683
684 if (flock.l_type != thiscase->a_type) {
685 tst_resm(TFAIL,
686 "Test case %d, GETLK: type = %d, "
687 "should be parent's first lock type of %d",
688 test + 1, flock.l_type,
689 thiscase->a_type);
690 fail = 1;
691 }
692 }
693 }
694
695 /*
696 * now try to set the lock, nonblocking
697 * This will succeed for NOBLOCK,
698 * fail for WILLBLOCK
699 */
700 flock.l_type = thiscase->c_type;
701 flock.l_whence = thiscase->c_whence;
702 flock.l_start = thiscase->c_start;
703 flock.l_len = thiscase->c_len;
704 flock.l_pid = 0;
705
706 if ((rc = fcntl(fd, F_SETLK, &flock)) < 0) {
707 if ((thiscase->c_flag) == NOBLOCK) {
708 tst_resm(TFAIL, "Attempt to set child NONBLOCKING "
709 "lock failed");
710 tst_resm(TFAIL, "Test case %d, errno = %d",
711 test + 1, errno);
712 fail = 1;
713 }
714 }
715
716 if ((thiscase->c_flag) == WILLBLOCK) {
717 if (rc != -1 || (errno != EACCES && errno != EAGAIN)) {
718 tst_resm(TFAIL,
719 "SETLK: rc = %d, errno = %d, -1/EAGAIN or EACCES "
720 "was expected", rc, errno);
721 fail = 1;
722 }
723 if (rc == 0) {
724 /* accidentally got the lock */
725 /* XXX how to clean up? */
726 (void)fcntl(fd, F_UNLCK, &flock);
727 }
728 /*
729 * Lock should succeed after blocking and parent releases
730 * lock, tell the parent to release the locks.
731 * Do the lock in this process, send the signal in a child
732 * process, so that the SETLKW actually uses the blocking
733 * mechanism in the kernel.
734 *
735 * XXX inherent race: we want to wait until the
736 * F_SETLKW has started, but we don't have a way to
737 * check that reliably in the child. (We'd
738 * need some way to have fcntl() atomically unblock a
739 * signal and wait for the lock.)
740 */
741 pid = FORK_OR_VFORK();
742 switch (pid) {
743 case -1:
744 tst_resm(TFAIL, "Fork failed");
745 fail = 1;
746 break;
747 case 0:
748 #ifdef UCLINUX
749 if (self_exec(argv0, "nd", 1, parent) < 0) {
750 tst_resm(TFAIL, "self_exec failed");
751 break;
752 }
753 #else
754 do_usleep_child();
755 #endif
756 break;
757
758 default:
759 if ((rc = fcntl(fd, F_SETLKW, &flock)) < 0) {
760 tst_resm(TFAIL, "Attempt to set child BLOCKING "
761 "lock failed");
762 tst_resm(TFAIL, "Test case %d, errno = %d",
763 test + 1, errno);
764 fail = 1;
765 }
766 waitpid(pid, &status, 0);
767 break;
768 }
769 }
770 if (fail) {
771 exit(1);
772 } else {
773 exit(0);
774 }
775 }
776
run_test(int file_flag,int file_mode,int seek,int start,int end)777 void run_test(int file_flag, int file_mode, int seek, int start, int end)
778 {
779 fail = 0;
780
781 for (test = start; test < end; test++) {
782 fd = SAFE_OPEN(cleanup, tmpname, file_flag, file_mode);
783
784 if (write(fd, FILEDATA, 10) < 0)
785 tst_brkm(TBROK, cleanup, "write() failed");
786
787 if (seek) {
788 SAFE_LSEEK(cleanup, fd, seek, 0);
789 }
790
791 thiscase = &testcases[test];
792 flock.l_type = thiscase->a_type;
793 flock.l_whence = thiscase->a_whence;
794 flock.l_start = thiscase->a_start;
795 flock.l_len = thiscase->a_len;
796
797 /* set the initial parent lock on the file */
798 if ((fcntl(fd, F_SETLK, &flock)) < 0) {
799 tst_resm(TFAIL, "First parent lock failed");
800 tst_resm(TFAIL, "Test case %d, errno = %d",
801 test + 1, errno);
802 fail = 1;
803 }
804
805 if ((thiscase->b_type) != SKIP) {
806 flock.l_type = thiscase->b_type;
807 flock.l_whence = thiscase->b_whence;
808 flock.l_start = thiscase->b_start;
809 flock.l_len = thiscase->b_len;
810
811 /* set the second parent lock */
812 if ((fcntl(fd, F_SETLK, &flock)) < 0) {
813 tst_resm(TFAIL, "Second parent lock failed");
814 tst_resm(TFAIL, "Test case %d, errno = %d",
815 test + 1, errno);
816 fail = 1;
817 }
818 }
819 if ((thiscase->c_type) == SKIP) {
820 close(fd);
821 tst_resm(TINFO, "skipping test %d", test + 1);
822 continue;
823 }
824
825 /* Mask SIG_USR1 before forking child, to avoid race */
826 (void)sighold(SIGUSR1);
827
828 /* flush the stdout to avoid garbled output */
829 fflush(stdout);
830
831 if ((child = FORK_OR_VFORK()) == 0) {
832 #ifdef UCLINUX
833 if (self_exec(argv0, "nddddddddd", 2, thiscase->c_type,
834 thiscase->c_whence, thiscase->c_start,
835 thiscase->c_len, thiscase->c_flag,
836 thiscase->a_type, fd, test, parent) < 0) {
837 tst_resm(TFAIL, "self_exec failed");
838 cleanup();
839 }
840 #else
841 dochild();
842 #endif
843 }
844 if (child < 0)
845 tst_brkm(TBROK|TERRNO, cleanup, "Fork failed");
846
847 if ((thiscase->c_flag) == WILLBLOCK) {
848 /*
849 * Wait for a signal from the child then remove
850 * blocking lock. Set a 60 second alarm to break the
851 * pause just in case the child never signals us.
852 */
853 alarm(TIME_OUT);
854 sigpause(SIGUSR1);
855
856 /* turn off the alarm timer */
857 alarm((unsigned)0);
858 if (got1 != 1)
859 tst_resm(TINFO, "Pause terminated without "
860 "signal SIGUSR1 from child");
861 got1 = 0;
862
863 /*
864 * setup lock structure for parent to delete
865 * blocking lock then wait for child to exit
866 */
867 flock.l_type = F_UNLCK;
868 flock.l_whence = 0;
869 flock.l_start = 0L;
870 flock.l_len = 0L;
871 if ((fcntl(fd, F_SETLK, &flock)) < 0) {
872 tst_resm(TFAIL, "Attempt to release parent "
873 "lock failed");
874 tst_resm(TFAIL, "Test case %d, errno = %d",
875 test + 1, errno);
876 fail = 1;
877 }
878 }
879 /*
880 * set a 60 second alarm to break the wait just in case the
881 * child doesn't terminate on its own accord
882 */
883 alarm(TIME_OUT);
884
885 /* wait for the child to terminate and close the file */
886 waitpid(child, &status, 0);
887 /* turn off the alarm clock */
888 alarm((unsigned)0);
889 if (status != 0) {
890 tst_resm(TFAIL, "tchild returned status 0x%x", status);
891 fail = 1;
892 }
893 close(fd);
894 if (fail)
895 tst_resm(TFAIL, "testcase:%d FAILED", test + 1);
896 else
897 tst_resm(TPASS, "testcase:%d PASSED", test + 1);
898 }
899 unlink(tmpname);
900 }
901
catch_alarm(int sig)902 void catch_alarm(int sig)
903 {
904 /*
905 * Timer has runout and child has not signaled, need
906 * to kill off the child as it appears it will not
907 * on its own accord. Check that it is still around
908 * as it may have terminated abnormally while parent
909 * was waiting for SIGUSR1 signal from it.
910 */
911 if (kill(child, 0) == 0) {
912 kill(child, SIGKILL);
913 perror("The child didnot terminate on its own accord");
914 }
915 }
916
catch1(int sig)917 void catch1(int sig)
918 {
919 struct sigaction act;
920
921 /*
922 * Set flag to let parent know that child is ready to have lock
923 * removed
924 */
925 memset(&act, 0, sizeof(act));
926 act.sa_handler = catch1;
927 sigemptyset(&act.sa_mask);
928 sigaddset(&act.sa_mask, SIGUSR1);
929 sigaction(SIGUSR1, &act, NULL);
930 got1++;
931 }
932
testcheck_end(int check_fail,char * msg)933 static void testcheck_end(int check_fail, char *msg)
934 {
935 if (check_fail)
936 tst_resm(TFAIL, "%s FAILED", msg);
937 else
938 tst_resm(TPASS, "%s PASSED", msg);
939 }
940
main(int ac,char ** av)941 int main(int ac, char **av)
942 {
943 int lc;
944
945 tst_parse_opts(ac, av, NULL, NULL);
946 #ifdef UCLINUX
947 argv0 = av[0];
948
949 maybe_run_child(&do_usleep_child, "nd", 1, &parent);
950 thiscase = malloc(sizeof(testcase));
951
952 maybe_run_child(&dochild, "nddddddddd", 2, &thiscase->c_type,
953 &thiscase->c_whence, &thiscase->c_start,
954 &thiscase->c_len, &thiscase->c_flag, &thiscase->a_type,
955 &fd, &test, &parent);
956 #endif
957
958 setup();
959
960 if (tst_fs_type(cleanup, ".") == TST_NFS_MAGIC)
961 NO_NFS = 0;
962
963 for (lc = 0; TEST_LOOPING(lc); lc++) {
964 tst_count = 0;
965
966 /* //block1: */
967 tst_resm(TINFO, "Enter block 1: without mandatory locking");
968 fail = 0;
969 /*
970 * try various file locks on an ordinary file without
971 * mandatory locking
972 */
973 (void)run_test(O_CREAT | O_RDWR | O_TRUNC, 0777, 0, 0, 36);
974 testcheck_end(fail, "Block 1, test 1");
975
976 /* Now try with negative values for L_start and L_len */
977 (void)run_test(O_CREAT | O_RDWR | O_TRUNC, 0777, 5, 36, 45);
978 testcheck_end(fail, "Block 1, test 2");
979
980 tst_resm(TINFO, "Exit block 1");
981
982 /* //block2: */
983 /*
984 * Skip block2 if test on NFS, since NFS does not support
985 * mandatory locking
986 */
987 tst_resm(TINFO, "Enter block 2: with mandatory locking");
988 if (NO_NFS) {
989 fail = 0;
990 /*
991 * Try various locks on a file with mandatory
992 * record locking this should behave the same
993 * as an ordinary file
994 */
995 (void)run_test(O_CREAT | O_RDWR | O_TRUNC,
996 S_ENFMT | S_IRUSR | S_IWUSR, 0, 0, 36);
997 testcheck_end(fail, "Block 2, test 1");
998
999 /* Now try negative values for L_start and L_len */
1000 (void)run_test(O_CREAT | O_RDWR | O_TRUNC,
1001 S_ENFMT | S_IRUSR | S_IWUSR, 5, 36, 45);
1002 testcheck_end(fail, "Block 2, test 2");
1003 } else {
1004 tst_resm(TCONF, "Skip block 2 as NFS does not"
1005 " support mandatory locking");
1006 }
1007
1008 tst_resm(TINFO, "Exit block 2");
1009
1010 /* //block3: */
1011 tst_resm(TINFO, "Enter block 3");
1012 fail = 0;
1013 /*
1014 * Check that proper error status is returned when invalid
1015 * argument used for WHENCE (negative value)
1016 */
1017
1018 fd = SAFE_OPEN(cleanup, tmpname, O_CREAT | O_RDWR | O_TRUNC,
1019 0777);
1020
1021 if (write(fd, FILEDATA, 10) < 0)
1022 tst_brkm(TBROK, cleanup, "write failed");
1023
1024 flock.l_type = F_WRLCK;
1025 flock.l_whence = -1;
1026 flock.l_start = 0L;
1027 flock.l_len = 0L;
1028
1029 if ((fcntl(fd, F_SETLK, &flock)) < 0) {
1030 if (errno != EINVAL) {
1031 tst_resm(TFAIL, "Expected %d got %d",
1032 EINVAL, errno);
1033 fail = 1;
1034 }
1035 } else {
1036 tst_resm(TFAIL, "Lock succeeded when it should have "
1037 "failed");
1038 fail = 1;
1039 }
1040
1041 close(fd);
1042 unlink(tmpname);
1043
1044 testcheck_end(fail, "Test with negative whence locking");
1045 tst_resm(TINFO, "Exit block 3");
1046
1047 /* //block4: */
1048 tst_resm(TINFO, "Enter block 4");
1049 fail = 0;
1050 /*
1051 * Check that a lock on end of file is still valid when
1052 * additional data is appended to end of file and a new
1053 * process attempts to lock new data
1054 */
1055 fd = SAFE_OPEN(cleanup, tmpname, O_CREAT | O_RDWR | O_TRUNC,
1056 0777);
1057
1058 if (write(fd, FILEDATA, 10) < 0)
1059 tst_brkm(TBROK, cleanup, "write failed");
1060
1061 thiscase = &testcases[58];
1062 flock.l_type = thiscase->a_type;
1063 flock.l_whence = thiscase->a_whence;
1064 flock.l_start = thiscase->a_start;
1065 flock.l_len = thiscase->a_len;
1066
1067 /* Set the initial parent lock on the file */
1068 if ((fcntl(fd, F_SETLK, &flock)) < 0) {
1069 tst_resm(TFAIL, "First parent lock failed");
1070 tst_resm(TFAIL, "Test case %d, errno = %d", 58, errno);
1071 fail = 1;
1072 }
1073
1074 /* Write some additional data to end of file */
1075 if (write(fd, FILEDATA, 10) < 0)
1076 tst_brkm(TBROK, cleanup, "write failed");
1077
1078 /* Mask signal to avoid race */
1079 if (sighold(SIGUSR1) < 0)
1080 tst_brkm(TBROK, cleanup, "sighold failed");
1081
1082 if ((child = FORK_OR_VFORK()) == 0) {
1083 #ifdef UCLINUX
1084 if (self_exec(argv0, "nddddddddd", 2, thiscase->c_type,
1085 thiscase->c_whence, thiscase->c_start,
1086 thiscase->c_len, thiscase->c_flag,
1087 thiscase->a_type, fd, test, parent) < 0) {
1088 tst_resm(TFAIL, "self_exec failed");
1089 cleanup();
1090 }
1091 #else
1092 dochild();
1093 #endif
1094 }
1095 if (child < 0)
1096 tst_brkm(TBROK|TERRNO, cleanup, "Fork failed");
1097
1098 /*
1099 * Wait for a signal from the child then remove blocking lock.
1100 * Set a 60 sec alarm to break the pause just in case the
1101 * child doesn't terminate on its own accord
1102 */
1103 (void)alarm(TIME_OUT);
1104
1105 (void)sigpause(SIGUSR1);
1106
1107 /* turn off the alarm timer */
1108 (void)alarm((unsigned)0);
1109 if (got1 != 1) {
1110 tst_resm(TINFO, "Pause terminated without signal "
1111 "SIGUSR1 from child");
1112 }
1113 got1 = 0;
1114
1115 /*
1116 * Set up lock structure for parent to delete
1117 * blocking lock then wait for child to exit
1118 */
1119 flock.l_type = F_UNLCK;
1120 flock.l_whence = 0;
1121 flock.l_start = 0L;
1122 flock.l_len = 0L;
1123 if ((fcntl(fd, F_SETLK, &flock)) < 0) {
1124 tst_resm(TFAIL, "Attempt to release parent lock "
1125 "failed");
1126 tst_resm(TFAIL, "Test case %d, errno = %d", test + 1,
1127 errno);
1128 fail = 1;
1129 }
1130
1131 /*
1132 * set a 60 sec alarm to break the wait just in case the
1133 * child doesn't terminate on its own accord
1134 */
1135 (void)alarm(TIME_OUT);
1136
1137 waitpid(child, &status, 0);
1138 if (WEXITSTATUS(status) != 0) {
1139 fail = 1;
1140 tst_resm(TFAIL, "child returned bad exit status");
1141 }
1142
1143 /* turn off the alarm clock */
1144 (void)alarm((unsigned)0);
1145 if (status != 0) {
1146 tst_resm(TFAIL, "child returned status 0x%x", status);
1147 fail = 1;
1148 }
1149 close(fd);
1150 unlink(tmpname);
1151
1152 testcheck_end(fail, "Test of locks on file");
1153 tst_resm(TINFO, "Exit block 4");
1154 }
1155 cleanup();
1156 tst_exit();
1157 }
1158