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