Home | History | Annotate | Download | only in ioctl
      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 
    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 
    152 static void help(void)
    153 {
    154 	printf("  -D <tty device> : for example, /dev/tty[0-9]\n");
    155 }
    156 
    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 
    176 static void cleanup(void)
    177 {
    178 	close(fd1);
    179 
    180 	tst_rmdir();
    181 }
    182