1/*
2 *
3 *   Copyright (c) International Business Machines  Corp., 2004
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 *
22 *    TEST IDENTIFIER	: fcntl24
23 *
24 *    EXECUTED BY	: anyone
25 *
26 *    TEST TITLE	: Basic test for fcntl(2) using F_SETLEASE & F_WRLCK argument.
27 *
28 *    TEST CASE TOTAL	: 1
29 *
30 *    WALL CLOCK TIME	: 1
31 *
32 *    CPU TYPES		: ALL
33 *
34 *    AUTHOR		: Robbie Williamson
35 *
36 *    TEST CASES
37 *
38 *	1.) fcntl(2) returns...(See Description)
39 *
40 *    INPUT SPECIFICATIONS
41 *	The standard options for system call tests are accepted.
42 *	(See the parse_opts(3) man page).
43 *
44 *    OUTPUT SPECIFICATIONS
45 *
46 *    DURATION
47 *	Terminates - with frequency and infinite modes.
48 *
49 *    SIGNALS
50 *	Uses SIGUSR1 to pause before test if option set.
51 *	(See the parse_opts(3) man page).
52 *
53 *    RESOURCES
54 *	None
55 *
56 *    ENVIRONMENTAL NEEDS
57 *      No run-time environmental needs.
58 *
59 *    SPECIAL PROCEDURAL REQUIREMENTS
60 *	None
61 *
62 *    INTERCASE DEPENDENCIES
63 *	None
64 *
65 *    DETAILED DESCRIPTION
66 *	This is a Phase I test for the fcntl(2) system call.  It is intended
67 *	to provide a limited exposure of the system call, for now.  It
68 *	should/will be extended when full functional tests are written for
69 *	fcntl(2).
70 *
71 *	Setup:
72 *	  Setup signal handling.
73 *	  Pause for SIGUSR1 if option specified.
74 *
75 *	Test:
76 *	 Loop if the proper options are given.
77 *	  Execute system call
78 *	  Check return code, if system call failed (return=-1)
79 *		Log the errno and Issue a FAIL message.
80 *	  Otherwise, Issue a PASS message.
81 *
82 *	Cleanup:
83 *	  Print errno log and/or timing stats if options given
84 *
85 *
86 *#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#*#**/
87
88#include <sys/types.h>
89#include <sys/stat.h>
90#include <fcntl.h>
91#include <unistd.h>
92#include <errno.h>
93#include <string.h>
94#include <signal.h>
95#include "test.h"
96
97void setup();
98void cleanup();
99
100char *TCID = "fcntl24";
101int TST_TOTAL = 1;
102
103char fname[255];
104int fd;
105
106int main(int ac, char **av)
107{
108	int lc;
109	long type;
110
111    /***************************************************************
112     * parse standard options
113     ***************************************************************/
114	tst_parse_opts(ac, av, NULL, NULL);
115
116    /***************************************************************
117     * perform global setup for test
118     ***************************************************************/
119	setup();
120
121	switch ((type = tst_fs_type(cleanup, "."))) {
122	case TST_NFS_MAGIC:
123	case TST_RAMFS_MAGIC:
124	case TST_TMPFS_MAGIC:
125		tst_brkm(TCONF, cleanup,
126			 "Cannot do fcntl on a file on %s filesystem",
127			 tst_fs_type_name(type));
128	break;
129	}
130
131    /***************************************************************
132     * check looping state if -c option given
133     ***************************************************************/
134	for (lc = 0; TEST_LOOPING(lc); lc++) {
135
136		tst_count = 0;
137
138#ifdef F_SETLEASE
139		/*
140		 * Call fcntl(2) with F_SETLEASE & F_WRLCK argument on fname
141		 */
142		TEST(fcntl(fd, F_SETLEASE, F_WRLCK));
143
144		/* check return code */
145		if (TEST_RETURN == -1) {
146			if (type == TST_OVERLAYFS_MAGIC && TEST_ERRNO == EAGAIN) {
147				tst_resm(TINFO | TTERRNO,
148					 "fcntl(F_SETLEASE, F_WRLCK) failed on overlayfs as expected");
149			} else {
150				tst_resm(TFAIL,
151					"fcntl(%s, F_SETLEASE, F_WRLCK) Failed, errno=%d : %s",
152					fname, TEST_ERRNO, strerror(TEST_ERRNO));
153			}
154		} else {
155			TEST(fcntl(fd, F_GETLEASE));
156			if (TEST_RETURN != F_WRLCK)
157				tst_resm(TFAIL,
158					 "fcntl(%s, F_GETLEASE) did not return F_WRLCK, returned %ld",
159					 fname, TEST_RETURN);
160			else {
161				TEST(fcntl(fd, F_SETLEASE, F_UNLCK));
162				if (TEST_RETURN != 0)
163						tst_resm(TFAIL,
164						 "fcntl(%s, F_SETLEASE, F_UNLCK) did not return 0, returned %ld",
165						 fname, TEST_RETURN);
166				else
167					tst_resm(TPASS,
168						 "fcntl(%s, F_SETLEASE, F_WRLCK)",
169						 fname);
170			}
171		}
172#else
173		tst_resm(TINFO, "F_SETLEASE not defined, skipping test");
174#endif
175	}
176
177	cleanup();
178	tst_exit();
179}
180
181/***************************************************************
182 * setup() - performs all ONE TIME setup for this test.
183 ***************************************************************/
184void setup(void)
185{
186
187	tst_sig(NOFORK, DEF_HANDLER, cleanup);
188
189	TEST_PAUSE;
190
191	tst_tmpdir();
192
193	sprintf(fname, "tfile_%d", getpid());
194	if ((fd = open(fname, O_RDWR | O_CREAT, 0777)) == -1) {
195		tst_brkm(TBROK, cleanup,
196			 "open(%s, O_RDWR|O_CREAT,0777) Failed, errno=%d : %s",
197			 fname, errno, strerror(errno));
198	}
199}
200
201/***************************************************************
202 * cleanup() - performs all ONE TIME cleanup for this test at
203 *		completion or premature exit.
204 ***************************************************************/
205void cleanup(void)
206{
207
208	/* close the file we've had open */
209	if (close(fd) == -1) {
210		tst_resm(TWARN, "close(%s) Failed, errno=%d : %s", fname, errno,
211			 strerror(errno));
212	}
213
214	tst_rmdir();
215
216}
217