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  *	fcntl18.c
23  *
24  * DESCRIPTION
25  *	Test to check the error conditions in fcntl system call
26  *
27  * USAGE
28  *	fcntl18
29  *
30  * HISTORY
31  *	07/2001 Ported by Wayne Boyer
32  *
33  * RESTRICTIONS
34  *	NONE
35  */
36 
37 #include <signal.h>
38 #include <errno.h>
39 #include <pwd.h>
40 #include <sys/types.h>
41 #include <sys/wait.h>
42 #include <sys/stat.h>
43 #include <sys/param.h>
44 #include <fcntl.h>
45 #include <unistd.h>
46 #include "test.h"
47 
48 #define INVAL_FLAG	-1
49 #define INVAL_MIN	(-2147483647L-1L)
50 
51 int fd;
52 char string[40] = "";
53 
54 char *TCID = "fcntl18";
55 int TST_TOTAL = 1;
56 struct passwd *pass;
57 
58 void setup(void);
59 void cleanup(void);
60 int fail;
61 
main(int ac,char ** av)62 int main(int ac, char **av)
63 {
64 	int retval;
65 	struct flock fl;
66 	int pid, status;
67 
68 	tst_parse_opts(ac, av, NULL, NULL);
69 
70 	setup();		/* global setup */
71 
72 /* //block1: */
73 #ifndef UCLINUX
74 	/* Skip since uClinux does not implement memory protection */
75 	tst_resm(TINFO, "Enter block 1");
76 	fail = 0;
77 	if ((fd = open("temp.dat", O_CREAT | O_RDWR, 0777)) < 0) {	//mode must be specified when O_CREATE is in the flag
78 		tst_resm(TFAIL, "file opening error");
79 		fail = 1;
80 	}
81 
82 	/* Error condition if address is bad */
83 	retval = fcntl(fd, F_GETLK, (struct flock *)INVAL_FLAG);
84 	if (errno == EFAULT) {
85 		tst_resm(TPASS, "Test F_GETLK: for errno EFAULT PASSED");
86 	} else {
87 		tst_resm(TFAIL, "Test F_GETLK: for errno EFAULT FAILED");
88 		fail = 1;
89 	}
90 	if (fail) {
91 		tst_resm(TINFO, "Block 1 FAILED");
92 	} else {
93 		tst_resm(TINFO, "Block 1 PASSED");
94 	}
95 	tst_resm(TINFO, "Exit block 1");
96 #else
97 	tst_resm(TINFO, "Skip block 1 on uClinux");
98 #endif
99 
100 /* //block2: */
101 #ifndef UCLINUX
102 	/* Skip since uClinux does not implement memory protection */
103 	tst_resm(TINFO, "Enter block 2");
104 	fail = 0;
105 	/* Error condition if address is bad */
106 	retval = fcntl(fd, F_GETLK64, (struct flock *)INVAL_FLAG);
107 	if (errno == EFAULT) {
108 		tst_resm(TPASS, "Test F_GETLK64: for errno EFAULT PASSED");
109 	} else {
110 		tst_resm(TFAIL, "Test F_GETLK64: for errno EFAULT FAILED");
111 		fail = 1;
112 	}
113 	if (fail) {
114 		tst_resm(TINFO, "Block 2 FAILED");
115 	} else {
116 		tst_resm(TINFO, "Block 2 PASSED");
117 	}
118 	tst_resm(TINFO, "Exit block 2");
119 #else
120 	tst_resm(TINFO, "Skip block 2 on uClinux");
121 #endif
122 
123 /* //block3: */
124 	tst_resm(TINFO, "Enter block 3");
125 	fail = 0;
126 	if ((pid = FORK_OR_VFORK()) == 0) {	/* child */
127 		fail = 0;
128 		pass = getpwnam("nobody");
129 		retval = setreuid(-1, pass->pw_uid);
130 		if (retval < 0) {
131 			tst_resm(TFAIL, "setreuid to user nobody failed, "
132 				 "errno: %d", errno);
133 			fail = 1;
134 		}
135 
136 		/* Error condition: invalid cmd */
137 		retval = fcntl(fd, INVAL_FLAG, &fl);
138 		if (errno == EINVAL) {
139 			tst_resm(TPASS, "Test for errno EINVAL PASSED");
140 		} else {
141 			tst_resm(TFAIL, "Test for errno EINVAL FAILED, "
142 				 "got: %d", errno);
143 			fail = 1;
144 		}
145 		exit(fail);
146 	} else {		/* parent */
147 		waitpid(pid, &status, 0);
148 		if (WEXITSTATUS(status) != 0) {
149 			tst_resm(TFAIL, "child returned bad exit status");
150 			fail = 1;
151 		}
152 		if (fail) {
153 			tst_resm(TINFO, "Block 3 FAILED");
154 		} else {
155 			tst_resm(TINFO, "Block 3 PASSED");
156 		}
157 	}
158 	tst_resm(TINFO, "Exit block 3");
159 
160 	cleanup();
161 	tst_exit();
162 
163 }
164 
165 /*
166  * setup()
167  *	performs all ONE TIME setup for this test
168  */
setup(void)169 void setup(void)
170 {
171 
172 	tst_sig(FORK, DEF_HANDLER, cleanup);
173 
174 	tst_require_root();
175 
176 	umask(0);
177 
178 	TEST_PAUSE;
179 
180 	tst_tmpdir();
181 
182 	sprintf(string, "./fcntl18.%d.1", getpid());
183 	unlink(string);
184 }
185 
186 /*
187  * cleanup()
188  *	performs all the ONE TIME cleanup for this test at completion or
189  *	or premature exit.
190  */
cleanup(void)191 void cleanup(void)
192 {
193 	/*
194 	 * print timing status if that option was specified.
195 	 * print errno log if that option was specified
196 	 */
197 	close(fd);
198 
199 	tst_rmdir();
200 
201 	unlink("temp.dat");
202 
203 }
204