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