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 * Test Name: llseek02 22 * Note that glibc exports the llseek syscall as lseek64. 23 * 24 * Test Description: 25 * Verify that, 26 * 1. llseek() returns -1 and sets errno to EINVAL, if the 'Whence' argument 27 * is not a proper value. 28 * 2. llseek() returns -1 and sets errno to EBADF, if the file handle of 29 * the specified file is not valid. 30 * 31 * Expected Result: 32 * llseek() should fail with return value -1 and set expected errno. 33 * 34 * Algorithm: 35 * Setup: 36 * Setup signal handling. 37 * Create temporary directory. 38 * Pause for SIGUSR1 if option specified. 39 * 40 * Test: 41 * Loop if the proper options are given. 42 * Execute system call 43 * Check return code, if system call failed (return=-1) 44 * if errno set == expected errno 45 * Issue sys call fails with expected return value and errno. 46 * Otherwise, 47 * Issue sys call fails with unexpected errno. 48 * Otherwise, 49 * Issue sys call returns unexpected value. 50 * 51 * Cleanup: 52 * Print errno log and/or timing stats if options given 53 * Delete the temporary directory(s)/file(s) created. 54 * 55 * Usage: <for command-line> 56 * llseek02 [-c n] [-e] [-i n] [-I x] [-P x] [-t] 57 * where, -c n : Run n copies concurrently. 58 * -i n : Execute test n times. 59 * -I x : Execute test for x seconds. 60 * -P x : Pause for x seconds between iterations. 61 * -t : Turn on syscall timing. 62 * 63 * HISTORY 64 * 07/2001 Ported by Wayne Boyer 65 * 66 * RESTRICTIONS: 67 * None. 68 */ 69 70 #ifndef _GNU_SOURCE 71 #define _GNU_SOURCE 72 #endif 73 74 #include <stdio.h> 75 #include <unistd.h> 76 #include <sys/types.h> 77 #include <errno.h> 78 #include <fcntl.h> 79 #include <utime.h> 80 #include <string.h> 81 #include <sys/stat.h> 82 #include <signal.h> 83 84 #include "test.h" 85 #include "safe_macros.h" 86 87 #define TEMP_FILE1 "tmp_file1" 88 #define TEMP_FILE2 "tmp_file2" 89 #define FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH 90 #define SEEK_TOP 10 91 92 char *TCID = "llseek02"; 93 int TST_TOTAL = 2; 94 95 int no_setup(); 96 int setup1(); /* setup function to test llseek() for EINVAL */ 97 int setup2(); /* setup function to test llseek() for EBADF */ 98 99 int fd1; /* file handle for testfile1 */ 100 int fd2; /* file handle for testfile2 */ 101 102 struct test_case_t { /* test case struct. to hold ref. test cond's */ 103 int fd; 104 int Whence; 105 char *desc; 106 int exp_errno; 107 int (*setupfunc) (); 108 } Test_cases[] = { 109 { 110 1, SEEK_TOP, "'whence' argument is not valid", EINVAL, setup1}, { 111 2, SEEK_SET, "'fd' is not an open file descriptor", EBADF, setup2}, 112 { 113 0, 0, NULL, 0, no_setup} 114 }; 115 116 void setup(); /* Main setup function of test */ 117 void cleanup(); /* cleanup function for the test */ 118 119 int main(int ac, char **av) 120 { 121 int lc; 122 int fildes; /* file handle for testfile */ 123 int whence; /* position of file handle in the file */ 124 char *test_desc; /* test specific error message */ 125 int ind; /* counter to test different test conditions */ 126 127 tst_parse_opts(ac, av, NULL, NULL); 128 129 setup(); 130 131 for (lc = 0; TEST_LOOPING(lc); lc++) { 132 133 tst_count = 0; 134 135 for (ind = 0; Test_cases[ind].desc != NULL; ind++) { 136 fildes = Test_cases[ind].fd; 137 test_desc = Test_cases[ind].desc; 138 whence = Test_cases[ind].Whence; 139 140 /* Assign the 'fd' values appropriatly */ 141 if (fildes == 1) { 142 fildes = fd1; 143 } else { 144 fildes = fd2; 145 } 146 147 /* 148 * Invoke llseek(2) to test different test conditions. 149 * Verify that it fails with -1 return value and 150 * sets appropriate errno. 151 */ 152 TEST(lseek64(fildes, (loff_t) 0, whence)); 153 154 if (TEST_RETURN != (loff_t) - 1) { 155 tst_resm(TFAIL, 156 "llseek() returned %ld, expected" 157 " -1, errno:%d", TEST_RETURN, 158 Test_cases[ind].exp_errno); 159 continue; 160 } 161 if (TEST_ERRNO == Test_cases[ind].exp_errno) { 162 tst_resm(TPASS, "llseek() fails, %s, errno:%d", 163 test_desc, TEST_ERRNO); 164 } else { 165 tst_resm(TFAIL, "llseek() fails, %s, errno:%d, " 166 "expected errno:%d", test_desc, 167 TEST_ERRNO, Test_cases[ind].exp_errno); 168 } 169 } 170 } 171 172 cleanup(); 173 174 tst_exit(); 175 } 176 177 /* 178 * setup() - performs all ONE TIME setup for this test. 179 * Create a temporary directory and change directory to it. 180 * Invoke individual test setup functions according to the order 181 * set in test struct. definition. 182 */ 183 void setup(void) 184 { 185 int ind; 186 187 tst_sig(NOFORK, DEF_HANDLER, cleanup); 188 189 TEST_PAUSE; 190 191 tst_tmpdir(); 192 193 /* call individual setup functions */ 194 for (ind = 0; Test_cases[ind].desc != NULL; ind++) { 195 Test_cases[ind].setupfunc(); 196 } 197 } 198 199 /* 200 * no_setup() - This is a dummy function which simply returns 0. 201 */ 202 int no_setup(void) 203 { 204 return 0; 205 } 206 207 /* 208 * setup1() - setup function for a test condition for which llseek(2) 209 * returns -1 and sets errno to EINVAL. 210 * Creat a temporary file for reading/writing and write some data 211 * into it. 212 * This function returns 0 on success. 213 */ 214 int setup1(void) 215 { 216 char write_buff[BUFSIZ]; /* buffer to hold data */ 217 218 /* Get the data to be written to temporary file */ 219 strcpy(write_buff, "abcdefg"); 220 221 /* Creat/open a temporary file under above directory */ 222 if ((fd1 = open(TEMP_FILE1, O_RDWR | O_CREAT, FILE_MODE)) == -1) { 223 tst_brkm(TBROK, cleanup, 224 "open(%s, O_RDWR|O_CREAT, %#o) Failed, errno=%d :%s", 225 TEMP_FILE1, FILE_MODE, errno, strerror(errno)); 226 } 227 228 /* Write data into temporary file */ 229 if (write(fd1, write_buff, sizeof(write_buff)) <= 0) { 230 tst_brkm(TBROK, cleanup, "write(2) on %s Failed, errno=%d : %s", 231 TEMP_FILE1, errno, strerror(errno)); 232 } 233 234 return 0; 235 } 236 237 /* 238 * setup2() - setup function for a test condition for which llseek(2) 239 * returns -1 and sets errno to EBADF. 240 * Creat a temporary file for reading/writing and close it. 241 * This function returns 0 on success. 242 */ 243 int setup2(void) 244 { 245 /* Creat/open a temporary file under above directory */ 246 if ((fd2 = open(TEMP_FILE2, O_RDWR | O_CREAT, FILE_MODE)) == -1) { 247 tst_brkm(TBROK, cleanup, 248 "open(%s, O_RDWR|O_CREAT, %#o) Failed, errno=%d :%s", 249 TEMP_FILE2, FILE_MODE, errno, strerror(errno)); 250 } 251 252 /* Close the temporary file created above */ 253 SAFE_CLOSE(cleanup, fd2); 254 255 return 0; 256 } 257 258 /* 259 * cleanup() - performs all ONE TIME cleanup for this test at 260 * completion or premature exit. 261 * Close the temporary file. 262 * Remove the test directory and testfile created in the setup. 263 */ 264 void cleanup(void) 265 { 266 267 /* Close the temporary file(s) created in setup1/setup2 */ 268 if (close(fd1) < 0) { 269 tst_brkm(TFAIL, NULL, "close(%s) Failed, errno=%d : %s:", 270 TEMP_FILE1, errno, strerror(errno)); 271 } 272 273 tst_rmdir(); 274 275 } 276