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  *	ioctl01.c
23  *
24  * DESCRIPTION
25  *	Testcase to check the errnos set by the ioctl(2) system call.
26  *
27  * ALGORITHM
28  *	1. EBADF: Pass an invalid fd to ioctl(fd, ..) and expect EBADF.
29  *	2. EFAULT: Pass an invalid address of arg in ioctl(fd, .., arg)
30  *	3. EINVAL: Pass invalid cmd in ioctl(fd, cmd, arg)
31  *	4. ENOTTY: Pass an non-streams fd in ioctl(fd, cmd, arg)
32  *	5. EFAULT: Pass a NULL address for termio
33  *
34  * USAGE:  <for command-line>
35  *  ioctl01 -D /dev/tty[0-9] [-c n] [-e] [-i n] [-I x] [-P x] [-t]
36  *     where,  -c n : Run n copies concurrently.
37  *             -e   : Turn on errno logging.
38  *             -i n : Execute test n times.
39  *             -I x : Execute test for x seconds.
40  *             -P x : Pause for x seconds between iterations.
41  *             -t   : Turn on syscall timing.
42  *
43  * HISTORY
44  *	07/2001 Ported by Wayne Boyer
45  *	04/2002 Fixes by wjhuie
46  *
47  * RESTRICTIONS
48  *      test must be run with the -D option
49  *      test may have to be run as root depending on the tty permissions
50  */
51 
52 #include <errno.h>
53 #include <fcntl.h>
54 #include <stdio.h>
55 #include <termio.h>
56 #include <termios.h>
57 #include "test.h"
58 #include "safe_macros.h"
59 
60 char *TCID = "ioctl01";
61 int TST_TOTAL = 5;
62 
63 #define	INVAL_IOCTL	9999999
64 
65 static void setup(void);
66 static void cleanup(void);
67 static void help(void);
68 
69 static int fd, fd1;
70 static int bfd = -1;
71 
72 static struct termio termio;
73 
74 static struct test_case_t {
75 	int *fd;
76 	int request;
77 	struct termio *s_tio;
78 	int error;
79 } TC[] = {
80 	/* file descriptor is invalid */
81 	{
82 	&bfd, TCGETA, &termio, EBADF},
83 	    /* termio address is invalid */
84 	{
85 	&fd, TCGETA, (struct termio *)-1, EFAULT},
86 	    /* command is invalid */
87 	    /* This errno value was changed from EINVAL to ENOTTY
88 	     * by kernel commit 07d106d0 and bbb63c51
89 	     */
90 	{
91 	&fd, INVAL_IOCTL, &termio, ENOTTY},
92 	    /* file descriptor is for a regular file */
93 	{
94 	&fd1, TCGETA, &termio, ENOTTY},
95 	    /* termio is NULL */
96 	{
97 	&fd, TCGETA, NULL, EFAULT}
98 };
99 
100 static int Devflag;
101 static char *devname;
102 
103 static option_t options[] = {
104 	{"D:", &Devflag, &devname},
105 	{NULL, NULL, NULL}
106 };
107 
main(int ac,char ** av)108 int main(int ac, char **av)
109 {
110 	int lc;
111 	int i;
112 
113 	tst_parse_opts(ac, av, options, &help);
114 
115 	if (!Devflag)
116 		tst_brkm(TBROK, NULL, "You must specify a tty device with "
117 			 "the -D option.");
118 
119 	tst_require_root();
120 
121 	setup();
122 
123 	fd = SAFE_OPEN(cleanup, devname, O_RDWR, 0777);
124 
125 	for (lc = 0; TEST_LOOPING(lc); lc++) {
126 
127 		tst_count = 0;
128 
129 		/* loop through the test cases */
130 		for (i = 0; i < TST_TOTAL; i++) {
131 
132 			TEST(ioctl(*(TC[i].fd), TC[i].request, TC[i].s_tio));
133 
134 			if (TEST_RETURN != -1) {
135 				tst_resm(TFAIL, "call succeeded unexpectedly");
136 				continue;
137 			}
138 
139 			if (TEST_ERRNO == TC[i].error)
140 				tst_resm(TPASS | TTERRNO, "failed as expected");
141 			else
142 				tst_resm(TFAIL | TTERRNO,
143 					 "failed unexpectedly; expected %d - %s",
144 					 TC[i].error, strerror(TC[i].error));
145 		}
146 	}
147 	cleanup();
148 
149 	tst_exit();
150 }
151 
help(void)152 static void help(void)
153 {
154 	printf("  -D <tty device> : for example, /dev/tty[0-9]\n");
155 }
156 
setup(void)157 static void setup(void)
158 {
159 	tst_sig(NOFORK, DEF_HANDLER, cleanup);
160 
161 	TEST_PAUSE;
162 
163 	/* make a temporary directory and cd to it */
164 	tst_tmpdir();
165 
166 	if (tst_kvercmp(3, 7, 0) < 0) {
167 		TC[2].error = EINVAL;
168 	}
169 
170 	/* create a temporary file */
171 	fd1 = open("x", O_CREAT, 0777);
172 	if (fd1 == -1)
173 		tst_resm(TFAIL | TERRNO, "Could not open test file");
174 }
175 
cleanup(void)176 static void cleanup(void)
177 {
178 	close(fd1);
179 
180 	tst_rmdir();
181 }
182