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
69typedef 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
85static 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
533static testcase *thiscase;
534static struct flock flock;
535static int parent, child, status, fail = 0;
536static int got1 = 0;
537static int fd;
538static int test;
539static char tmpname[40];
540
541#define FILEDATA	"ten bytes!"
542
543void catch1(int sig);
544void catch_alarm(int sig);
545
546char *TCID = "fcntl14";
547int TST_TOTAL = 1;
548int NO_NFS = 1;
549
550#ifdef UCLINUX
551static char *argv0;
552#endif
553
554void cleanup(void)
555{
556	tst_rmdir();
557}
558
559void 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
593void 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
602void do_usleep_child(void)
603{
604	usleep(100000);		/* XXX how long is long enough? */
605	wake_parent();
606	exit(0);
607}
608
609void 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
777void 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
902void 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
917void 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
933static 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
941int 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